Remove debug prints
This commit is contained in:
parent
683f5c1438
commit
af22f7aaa9
|
@ -21,6 +21,8 @@ class Polyhedron:
|
||||||
self._faces = None
|
self._faces = None
|
||||||
self._vertices = None
|
self._vertices = None
|
||||||
self._mesh = None
|
self._mesh = None
|
||||||
|
self._centroid = None
|
||||||
|
self._max_z = None
|
||||||
self._geometry = GeometryHelper()
|
self._geometry = GeometryHelper()
|
||||||
|
|
||||||
def _position_of(self, point):
|
def _position_of(self, point):
|
||||||
|
@ -65,16 +67,14 @@ class Polyhedron:
|
||||||
for point in points:
|
for point in points:
|
||||||
face.append(self._position_of(point))
|
face.append(self._position_of(point))
|
||||||
self._faces.append(face)
|
self._faces.append(face)
|
||||||
self._faces = np.asarray(self._faces)
|
#self._faces = np.asarray(self._faces)
|
||||||
return self._faces
|
return self._faces
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _polyhedron_mesh(self):
|
def _polyhedron_mesh(self):
|
||||||
|
|
||||||
if self._mesh is None:
|
if self._mesh is None:
|
||||||
self._mesh = Trimesh(vertices=np.asarray(self.vertices), faces=np.asarray(self.faces))
|
self._mesh = Trimesh(vertices=self.vertices, faces=self.faces)
|
||||||
if not self._mesh.is_volume:
|
|
||||||
print('The geometry is not a closed volume')
|
|
||||||
return None
|
|
||||||
return self._mesh
|
return self._mesh
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -84,7 +84,11 @@ class Polyhedron:
|
||||||
:return: float
|
:return: float
|
||||||
"""
|
"""
|
||||||
if self._volume is None:
|
if self._volume is None:
|
||||||
self._volume = self._polyhedron_mesh.volume
|
if not self._polyhedron_mesh.is_volume:
|
||||||
|
print('The geometry is not a closed volume')
|
||||||
|
self._volume = np.inf
|
||||||
|
else:
|
||||||
|
self._volume = self._polyhedron_mesh.volume
|
||||||
return self._volume
|
return self._volume
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
@ -81,7 +81,7 @@ class CityGml:
|
||||||
surface_type = next(iter(bound))
|
surface_type = next(iter(bound))
|
||||||
if 'lod2MultiSurface' in bound[surface_type]:
|
if 'lod2MultiSurface' in bound[surface_type]:
|
||||||
lod = 2
|
lod = 2
|
||||||
surfaces = CityGml._lod2(bound)
|
surfaces = surfaces + CityGml._lod2(bound)
|
||||||
if 'lod3Solid' in o['Building']:
|
if 'lod3Solid' in o['Building']:
|
||||||
lod += 4
|
lod += 4
|
||||||
if 'lod4Solid' in o['Building']:
|
if 'lod4Solid' in o['Building']:
|
||||||
|
@ -142,13 +142,13 @@ class CityGml:
|
||||||
def _lod2(bound):
|
def _lod2(bound):
|
||||||
surfaces = []
|
surfaces = []
|
||||||
for surface_type in iter(bound):
|
for surface_type in iter(bound):
|
||||||
for s in bound[surface_type]['lod2MultiSurface']['MultiSurface']['surfaceMember']:
|
try:
|
||||||
try:
|
print(bound)
|
||||||
surfaces = [Surface(s['Polygon']['exterior']['LinearRing']['posList']['#text'],
|
surfaces = [Surface(s['Polygon']['exterior']['LinearRing']['posList']['#text'],
|
||||||
surface_type=GeometryHelper.gml_surface_to_libs(surface_type))
|
surface_type=GeometryHelper.gml_surface_to_libs(surface_type))
|
||||||
for s in bound[surface_type]['lod2MultiSurface']['MultiSurface']['surfaceMember']]
|
for s in bound[surface_type]['lod2MultiSurface']['MultiSurface']['surfaceMember']]
|
||||||
except TypeError:
|
except TypeError:
|
||||||
surfaces = [Surface(s['Polygon']['exterior']['LinearRing']['posList'],
|
surfaces = [Surface(s['Polygon']['exterior']['LinearRing']['posList'],
|
||||||
surface_type=GeometryHelper.gml_surface_to_libs(surface_type))
|
surface_type=GeometryHelper.gml_surface_to_libs(surface_type))
|
||||||
for s in bound[surface_type]['lod2MultiSurface']['MultiSurface']['surfaceMember']]
|
for s in bound[surface_type]['lod2MultiSurface']['MultiSurface']['surfaceMember']]
|
||||||
return surfaces
|
return surfaces
|
||||||
|
|
|
@ -17,10 +17,10 @@ class UsBasePhysicsParameters:
|
||||||
"""
|
"""
|
||||||
UsBasePhysicsParameters class
|
UsBasePhysicsParameters class
|
||||||
"""
|
"""
|
||||||
def __init__(self, climate_zone, city_objects, function_to_type, base_path):
|
def __init__(self, climate_zone, buildings, function_to_type, base_path):
|
||||||
self._climate_zone = climate_zone
|
self._climate_zone = climate_zone
|
||||||
self._city_objects = city_objects
|
self._buildings = buildings
|
||||||
|
print(buildings)
|
||||||
# load US Library
|
# load US Library
|
||||||
path = str(Path.cwd() / base_path / 'us_constructions.xml')
|
path = str(Path.cwd() / base_path / 'us_constructions.xml')
|
||||||
with open(path) as xml:
|
with open(path) as xml:
|
||||||
|
@ -30,24 +30,25 @@ class UsBasePhysicsParameters:
|
||||||
path = str(Path.cwd() / base_path / 'us_archetypes.xml')
|
path = str(Path.cwd() / base_path / 'us_archetypes.xml')
|
||||||
with open(path) as xml:
|
with open(path) as xml:
|
||||||
self._archetypes = xmltodict.parse(xml.read(), force_list='layer')
|
self._archetypes = xmltodict.parse(xml.read(), force_list='layer')
|
||||||
for city_object in self._city_objects:
|
for building in self._buildings:
|
||||||
building_type = function_to_type(city_object.function)
|
|
||||||
|
building_type = function_to_type(building.function)
|
||||||
if building_type is None:
|
if building_type is None:
|
||||||
return
|
return
|
||||||
archetype = self._search_archetype(building_type,
|
archetype = self._search_archetype(building_type,
|
||||||
UsToLibraryTypes.yoc_to_standard(city_object.year_of_construction),
|
UsToLibraryTypes.yoc_to_standard(building.year_of_construction),
|
||||||
self._climate_zone)
|
self._climate_zone)
|
||||||
# ToDo: remove this in the future
|
# ToDo: remove this in the future
|
||||||
# ToDo: Raise WrongArchetype if not all the surface types are defined for the given city_object
|
# ToDo: Raise WrongArchetype if not all the surface types are defined for the given city_object
|
||||||
if archetype is None:
|
if archetype is None:
|
||||||
print(building_type, UsToLibraryTypes.yoc_to_standard(city_object.year_of_construction),
|
print(building_type, UsToLibraryTypes.yoc_to_standard(building.year_of_construction),
|
||||||
self._climate_zone)
|
self._climate_zone)
|
||||||
raise Exception('Archetype not found for building')
|
raise Exception('Archetype not found for building')
|
||||||
|
|
||||||
city_object.average_storey_height = archetype['average_storey_height']['#text']
|
building.average_storey_height = archetype['average_storey_height']['#text']
|
||||||
city_object.storeys_above_ground = archetype['number_of_storeys']['#text']
|
building.storeys_above_ground = archetype['number_of_storeys']['#text']
|
||||||
|
|
||||||
for thermal_zone in city_object.thermal_zones:
|
for thermal_zone in building.thermal_zones:
|
||||||
thermal_zone.effective_thermal_capacity = archetype['thermal_capacity']['#text']
|
thermal_zone.effective_thermal_capacity = archetype['thermal_capacity']['#text']
|
||||||
thermal_zone.additional_thermal_bridge_u_value = archetype['extra_loses_due_to_thermal_bridges']['#text']
|
thermal_zone.additional_thermal_bridge_u_value = archetype['extra_loses_due_to_thermal_bridges']['#text']
|
||||||
thermal_zone.indirectly_heated_area_ratio = archetype['indirect_heated_ratio']['#text']
|
thermal_zone.indirectly_heated_area_ratio = archetype['indirect_heated_ratio']['#text']
|
||||||
|
|
|
@ -6,9 +6,6 @@ pyproj~=2.6.1.post1
|
||||||
pyny3d~=0.2
|
pyny3d~=0.2
|
||||||
matplotlib~=3.2.1
|
matplotlib~=3.2.1
|
||||||
Shapely~=1.7.0
|
Shapely~=1.7.0
|
||||||
|
|
||||||
# MonthlyEnergyBalance
|
|
||||||
|
|
||||||
pandas~=1.0.4
|
pandas~=1.0.4
|
||||||
pip~=20.1.1
|
pip~=20.1.1
|
||||||
pyzmq~=19.0.1
|
pyzmq~=19.0.1
|
||||||
|
@ -52,4 +49,5 @@ attrs~=19.3.0
|
||||||
pyrsistent~=0.16.0
|
pyrsistent~=0.16.0
|
||||||
cycler~=0.10.0
|
cycler~=0.10.0
|
||||||
kiwisolver~=1.2.0
|
kiwisolver~=1.2.0
|
||||||
zipp~=3.1.0
|
zipp~=3.1.0
|
||||||
|
reverse_geocoder~=1.5.1
|
|
@ -24,7 +24,7 @@ class TestGeometryFactory(TestCase):
|
||||||
|
|
||||||
def _get_citygml(self):
|
def _get_citygml(self):
|
||||||
if self._city_gml is None:
|
if self._city_gml is None:
|
||||||
file_path = (self._example_path / 'lod2_buildings.gml').resolve()
|
file_path = (self._example_path / 'buildings.gml').resolve()
|
||||||
self._city_gml = GeometryFactory('citygml', file_path).city
|
self._city_gml = GeometryFactory('citygml', file_path).city
|
||||||
self.assertIsNotNone(self._city_gml, 'city is none')
|
self.assertIsNotNone(self._city_gml, 'city is none')
|
||||||
return self._city_gml
|
return self._city_gml
|
||||||
|
@ -36,8 +36,8 @@ class TestGeometryFactory(TestCase):
|
||||||
"""
|
"""
|
||||||
city = self._get_citygml()
|
city = self._get_citygml()
|
||||||
self.assertIsNotNone(city.city_objects, 'city_objects is none')
|
self.assertIsNotNone(city.city_objects, 'city_objects is none')
|
||||||
for city_object in city.city_objects:
|
for building in city.buildings:
|
||||||
self.assertIsNotNone(city.city_object(city_object.name), 'city_object return none')
|
self.assertIsNotNone(city.city_object(building.name), 'city_object return none')
|
||||||
self.assertIsNotNone(city.srs_name, 'srs_name is none')
|
self.assertIsNotNone(city.srs_name, 'srs_name is none')
|
||||||
self.assertIsNotNone(city.lower_corner, 'lower_corner is none')
|
self.assertIsNotNone(city.lower_corner, 'lower_corner is none')
|
||||||
self.assertIsNotNone(city.upper_corner, 'upper_corner is none')
|
self.assertIsNotNone(city.upper_corner, 'upper_corner is none')
|
||||||
|
@ -79,8 +79,8 @@ class TestGeometryFactory(TestCase):
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
city = self._get_citygml()
|
city = self._get_citygml()
|
||||||
for city_object in city.buildings:
|
for building in city.buildings:
|
||||||
for surface in city_object.surfaces:
|
for surface in building.surfaces:
|
||||||
self.assertIsNotNone(surface.name, 'surface name is none')
|
self.assertIsNotNone(surface.name, 'surface name is none')
|
||||||
self.assertIsNotNone(surface.area, 'surface area is none')
|
self.assertIsNotNone(surface.area, 'surface area is none')
|
||||||
self.assertIsNotNone(surface.type, 'surface type is none')
|
self.assertIsNotNone(surface.type, 'surface type is none')
|
||||||
|
@ -110,8 +110,8 @@ class TestGeometryFactory(TestCase):
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
city = self._get_citygml()
|
city = self._get_citygml()
|
||||||
for city_object in city.buildings:
|
for building in city.buildings:
|
||||||
for thermal_zone in city_object.thermal_zones:
|
for thermal_zone in building.thermal_zones:
|
||||||
self.assertIsNotNone(thermal_zone.surfaces, 'thermal_zone surfaces is none')
|
self.assertIsNotNone(thermal_zone.surfaces, 'thermal_zone surfaces is none')
|
||||||
self.assertIsNotNone(thermal_zone.bounded, 'thermal_zone bounded is none')
|
self.assertIsNotNone(thermal_zone.bounded, 'thermal_zone bounded is none')
|
||||||
self.assertIsNotNone(thermal_zone.floor_area, 'thermal_zone floor_area is none')
|
self.assertIsNotNone(thermal_zone.floor_area, 'thermal_zone floor_area is none')
|
||||||
|
@ -136,8 +136,8 @@ class TestGeometryFactory(TestCase):
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
city = self._get_citygml()
|
city = self._get_citygml()
|
||||||
for city_object in city.buildings:
|
for building in city.buildings:
|
||||||
for thermal_zone in city_object.thermal_zones:
|
for thermal_zone in building.thermal_zones:
|
||||||
for thermal_boundary in thermal_zone.bounded:
|
for thermal_boundary in thermal_zone.bounded:
|
||||||
self.assertIsNotNone(thermal_boundary.type, 'thermal_boundary type is none')
|
self.assertIsNotNone(thermal_boundary.type, 'thermal_boundary type is none')
|
||||||
self.assertIsNotNone(thermal_boundary.area, 'thermal_boundary area is none')
|
self.assertIsNotNone(thermal_boundary.area, 'thermal_boundary area is none')
|
||||||
|
@ -166,8 +166,8 @@ class TestGeometryFactory(TestCase):
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
city = self._get_citygml()
|
city = self._get_citygml()
|
||||||
for city_object in city.buildings:
|
for building in city.buildings:
|
||||||
for thermal_zone in city_object.thermal_zones:
|
for thermal_zone in building.thermal_zones:
|
||||||
for thermal_boundary in thermal_zone.bounded:
|
for thermal_boundary in thermal_zone.bounded:
|
||||||
for thermal_opening in thermal_boundary.thermal_openings:
|
for thermal_opening in thermal_boundary.thermal_openings:
|
||||||
self.assertTrue(thermal_opening.frame_ratio == 0, 'thermal_opening frame_ratio was not 0')
|
self.assertTrue(thermal_opening.frame_ratio == 0, 'thermal_opening frame_ratio was not 0')
|
||||||
|
|
|
@ -25,7 +25,7 @@ class TestPhysicsFactory(TestCase):
|
||||||
|
|
||||||
def _get_citygml(self):
|
def _get_citygml(self):
|
||||||
if self._city_gml is None:
|
if self._city_gml is None:
|
||||||
file_path = (self._example_path / 'lod2_buildings.gml').resolve()
|
file_path = (self._example_path / 'buildings.gml').resolve()
|
||||||
self._city_gml = GeometryFactory('citygml', file_path).city
|
self._city_gml = GeometryFactory('citygml', file_path).city
|
||||||
self.assertIsNotNone(self._city_gml, 'city is none')
|
self.assertIsNotNone(self._city_gml, 'city is none')
|
||||||
return self._city_gml
|
return self._city_gml
|
||||||
|
@ -33,6 +33,7 @@ class TestPhysicsFactory(TestCase):
|
||||||
def _get_city_with_physics(self):
|
def _get_city_with_physics(self):
|
||||||
if self._nyc_with_physics is None:
|
if self._nyc_with_physics is None:
|
||||||
self._nyc_with_physics = self._get_citygml()
|
self._nyc_with_physics = self._get_citygml()
|
||||||
|
print(self._nyc_with_physics)
|
||||||
PhysicsFactory('us_new_york_city', self._nyc_with_physics, base_path=self._example_path)
|
PhysicsFactory('us_new_york_city', self._nyc_with_physics, base_path=self._example_path)
|
||||||
return self._nyc_with_physics
|
return self._nyc_with_physics
|
||||||
|
|
||||||
|
@ -42,10 +43,10 @@ class TestPhysicsFactory(TestCase):
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
city = self._get_city_with_physics()
|
city = self._get_city_with_physics()
|
||||||
for city_object in city.buildings:
|
for building in city.buildings:
|
||||||
self.assertIsNotNone(city_object.average_storey_height, 'average_storey_height is none')
|
self.assertIsNotNone(building.average_storey_height, 'average_storey_height is none')
|
||||||
self.assertIsNotNone(city_object.storeys_above_ground, 'storeys_above_ground is none')
|
self.assertIsNotNone(building.storeys_above_ground, 'storeys_above_ground is none')
|
||||||
for thermal_zone in city_object.thermal_zones:
|
for thermal_zone in building.thermal_zones:
|
||||||
self.assertIsNotNone(thermal_zone.effective_thermal_capacity, 'effective_thermal_capacity is none')
|
self.assertIsNotNone(thermal_zone.effective_thermal_capacity, 'effective_thermal_capacity is none')
|
||||||
self.assertIsNotNone(thermal_zone.additional_thermal_bridge_u_value,
|
self.assertIsNotNone(thermal_zone.additional_thermal_bridge_u_value,
|
||||||
'additional_thermal_bridge_u_value is none')
|
'additional_thermal_bridge_u_value is none')
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -39,7 +39,6 @@ class UsBaseUsageParameters:
|
||||||
city_object.usage_zones = [UsBaseUsageParameters._parse_zone_usage_type(zone_usage_type, usage_zone)]
|
city_object.usage_zones = [UsBaseUsageParameters._parse_zone_usage_type(zone_usage_type, usage_zone)]
|
||||||
break
|
break
|
||||||
if city_object.usage_zones is None:
|
if city_object.usage_zones is None:
|
||||||
print(city_object.function)
|
|
||||||
raise Exception('Usage not found for building function')
|
raise Exception('Usage not found for building function')
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
|
@ -1,469 +0,0 @@
|
||||||
####################################################################################
|
|
||||||
Jedi - an awesome autocompletion, static analysis and refactoring library for Python
|
|
||||||
####################################################################################
|
|
||||||
|
|
||||||
.. image:: http://isitmaintained.com/badge/open/davidhalter/jedi.svg
|
|
||||||
:target: https://github.com/davidhalter/jedi/issues
|
|
||||||
:alt: The percentage of open issues and pull requests
|
|
||||||
|
|
||||||
.. image:: http://isitmaintained.com/badge/resolution/davidhalter/jedi.svg
|
|
||||||
:target: https://github.com/davidhalter/jedi/issues
|
|
||||||
:alt: The resolution time is the median time an issue or pull request stays open.
|
|
||||||
|
|
||||||
.. image:: https://travis-ci.org/davidhalter/jedi.svg?branch=master
|
|
||||||
:target: https://travis-ci.org/davidhalter/jedi
|
|
||||||
:alt: Linux Tests
|
|
||||||
|
|
||||||
.. image:: https://ci.appveyor.com/api/projects/status/mgva3bbawyma1new/branch/master?svg=true
|
|
||||||
:target: https://ci.appveyor.com/project/davidhalter/jedi/branch/master
|
|
||||||
:alt: Windows Tests
|
|
||||||
|
|
||||||
.. image:: https://coveralls.io/repos/davidhalter/jedi/badge.svg?branch=master
|
|
||||||
:target: https://coveralls.io/r/davidhalter/jedi
|
|
||||||
:alt: Coverage status
|
|
||||||
|
|
||||||
|
|
||||||
Jedi is a static analysis tool for Python that is typically used in
|
|
||||||
IDEs/editors plugins. Jedi has a focus on autocompletion and goto
|
|
||||||
functionality. Other features include refactoring, code search and finding
|
|
||||||
references.
|
|
||||||
|
|
||||||
Jedi has a simple API to work with. There is a reference implementation as a
|
|
||||||
`VIM-Plugin <https://github.com/davidhalter/jedi-vim>`_. Autocompletion in your
|
|
||||||
REPL is also possible, IPython uses it natively and for the CPython REPL you
|
|
||||||
can install it. Jedi is well tested and bugs should be rare.
|
|
||||||
|
|
||||||
Jedi can currently be used with the following editors/projects:
|
|
||||||
|
|
||||||
- Vim (jedi-vim_, YouCompleteMe_, deoplete-jedi_, completor.vim_)
|
|
||||||
- `Visual Studio Code`_ (via `Python Extension <https://marketplace.visualstudio.com/items?itemName=ms-python.python>`_)
|
|
||||||
- Emacs (Jedi.el_, company-mode_, elpy_, anaconda-mode_, ycmd_)
|
|
||||||
- Sublime Text (SublimeJEDI_ [ST2 + ST3], anaconda_ [only ST3])
|
|
||||||
- TextMate_ (Not sure if it's actually working)
|
|
||||||
- Kate_ version 4.13+ supports it natively, you have to enable it, though. [`see
|
|
||||||
<https://projects.kde.org/projects/kde/applications/kate/repository/show?rev=KDE%2F4.13>`_]
|
|
||||||
- Atom_ (autocomplete-python-jedi_)
|
|
||||||
- `GNOME Builder`_ (with support for GObject Introspection)
|
|
||||||
- Gedit (gedi_)
|
|
||||||
- wdb_ - Web Debugger
|
|
||||||
- `Eric IDE`_ (Available as a plugin)
|
|
||||||
- `IPython 6.0.0+ <https://ipython.readthedocs.io/en/stable/whatsnew/version6.html>`_
|
|
||||||
|
|
||||||
and many more!
|
|
||||||
|
|
||||||
Here are some pictures taken from jedi-vim_:
|
|
||||||
|
|
||||||
.. image:: https://github.com/davidhalter/jedi/raw/master/docs/_screenshots/screenshot_complete.png
|
|
||||||
|
|
||||||
Completion for almost anything:
|
|
||||||
|
|
||||||
.. image:: https://github.com/davidhalter/jedi/raw/master/docs/_screenshots/screenshot_function.png
|
|
||||||
|
|
||||||
Documentation:
|
|
||||||
|
|
||||||
.. image:: https://github.com/davidhalter/jedi/raw/master/docs/_screenshots/screenshot_pydoc.png
|
|
||||||
|
|
||||||
|
|
||||||
Get the latest version from `github <https://github.com/davidhalter/jedi>`_
|
|
||||||
(master branch should always be kind of stable/working).
|
|
||||||
|
|
||||||
Docs are available at `https://jedi.readthedocs.org/en/latest/
|
|
||||||
<https://jedi.readthedocs.org/en/latest/>`_. Pull requests with enhancements
|
|
||||||
and/or fixes are awesome and most welcome. Jedi uses `semantic versioning
|
|
||||||
<https://semver.org/>`_.
|
|
||||||
|
|
||||||
If you want to stay up-to-date (News / RFCs), please subscribe to this `github
|
|
||||||
thread <https://github.com/davidhalter/jedi/issues/1063>`_.:
|
|
||||||
|
|
||||||
Issues & Questions
|
|
||||||
==================
|
|
||||||
|
|
||||||
You can file issues and questions in the `issue tracker
|
|
||||||
<https://github.com/davidhalter/jedi/>`. Alternatively you can also ask on
|
|
||||||
`Stack Overflow <https://stackoverflow.com/questions/tagged/python-jedi>`_ with
|
|
||||||
the label ``python-jedi``.
|
|
||||||
|
|
||||||
Installation
|
|
||||||
============
|
|
||||||
|
|
||||||
`Check out the docs <https://jedi.readthedocs.org/en/latest/docs/installation.html>`_.
|
|
||||||
|
|
||||||
Features and Limitations
|
|
||||||
========================
|
|
||||||
|
|
||||||
Jedi's features are listed here:
|
|
||||||
`Features <https://jedi.readthedocs.org/en/latest/docs/features.html>`_.
|
|
||||||
|
|
||||||
You can run Jedi on CPython 2.7 or 3.5+ but it should also
|
|
||||||
understand code that is older than those versions. Additionally you should be
|
|
||||||
able to use `Virtualenvs <https://jedi.readthedocs.org/en/latest/docs/api.html#environments>`_
|
|
||||||
very well.
|
|
||||||
|
|
||||||
Tips on how to use Jedi efficiently can be found `here
|
|
||||||
<https://jedi.readthedocs.org/en/latest/docs/features.html#recipes>`_.
|
|
||||||
|
|
||||||
API
|
|
||||||
---
|
|
||||||
|
|
||||||
You can find a comprehensive documentation for the
|
|
||||||
`API here <https://jedi.readthedocs.org/en/latest/docs/api.html>`_.
|
|
||||||
|
|
||||||
Autocompletion / Goto / Documentation
|
|
||||||
-------------------------------------
|
|
||||||
|
|
||||||
There are the following commands:
|
|
||||||
|
|
||||||
- ``jedi.Script.goto``
|
|
||||||
- ``jedi.Script.infer``
|
|
||||||
- ``jedi.Script.help``
|
|
||||||
- ``jedi.Script.complete``
|
|
||||||
- ``jedi.Script.get_references``
|
|
||||||
- ``jedi.Script.get_signatures``
|
|
||||||
- ``jedi.Script.get_context``
|
|
||||||
|
|
||||||
The returned objects are very powerful and are really all you might need.
|
|
||||||
|
|
||||||
Autocompletion in your REPL (IPython, etc.)
|
|
||||||
-------------------------------------------
|
|
||||||
|
|
||||||
Jedi is a dependency of IPython. Autocompletion in IPython with Jedi is
|
|
||||||
therefore possible without additional configuration.
|
|
||||||
|
|
||||||
Here is an `example video <https://vimeo.com/122332037>`_ how REPL completion
|
|
||||||
can look like.
|
|
||||||
For the ``python`` shell you can enable tab completion in a `REPL
|
|
||||||
<https://jedi.readthedocs.org/en/latest/docs/usage.html#tab-completion-in-the-python-shell>`_.
|
|
||||||
|
|
||||||
Static Analysis
|
|
||||||
---------------
|
|
||||||
|
|
||||||
For a lot of forms of static analysis, you can try to use
|
|
||||||
``jedi.Script(...).get_names``. It will return a list of names that you can
|
|
||||||
then filter and work with. There is also a way to list the syntax errors in a
|
|
||||||
file: ``jedi.Script.get_syntax_errors``.
|
|
||||||
|
|
||||||
|
|
||||||
Refactoring
|
|
||||||
-----------
|
|
||||||
|
|
||||||
Jedi supports the following refactorings:
|
|
||||||
|
|
||||||
- ``jedi.Script.inline``
|
|
||||||
- ``jedi.Script.rename``
|
|
||||||
- ``jedi.Script.extract_function``
|
|
||||||
- ``jedi.Script.extract_variable``
|
|
||||||
|
|
||||||
Code Search
|
|
||||||
-----------
|
|
||||||
|
|
||||||
There is support for module search with ``jedi.Script.search``, and project
|
|
||||||
search for ``jedi.Project.search``. The way to search is either by providing a
|
|
||||||
name like ``foo`` or by using dotted syntax like ``foo.bar``. Additionally you
|
|
||||||
can provide the API type like ``class foo.bar.Bar``. There are also the
|
|
||||||
functions ``jedi.Script.complete_search`` and ``jedi.Project.complete_search``.
|
|
||||||
|
|
||||||
Development
|
|
||||||
===========
|
|
||||||
|
|
||||||
There's a pretty good and extensive `development documentation
|
|
||||||
<https://jedi.readthedocs.org/en/latest/docs/development.html>`_.
|
|
||||||
|
|
||||||
Testing
|
|
||||||
=======
|
|
||||||
|
|
||||||
The test suite uses ``pytest``::
|
|
||||||
|
|
||||||
pip install pytest
|
|
||||||
|
|
||||||
If you want to test only a specific Python version (e.g. Python 3.8), it is as
|
|
||||||
easy as::
|
|
||||||
|
|
||||||
python3.8 -m pytest
|
|
||||||
|
|
||||||
For more detailed information visit the `testing documentation
|
|
||||||
<https://jedi.readthedocs.org/en/latest/docs/testing.html>`_.
|
|
||||||
|
|
||||||
Acknowledgements
|
|
||||||
================
|
|
||||||
|
|
||||||
Thanks a lot to all the
|
|
||||||
`contributors <https://jedi.readthedocs.org/en/latest/docs/acknowledgements.html>`_!
|
|
||||||
|
|
||||||
|
|
||||||
.. _jedi-vim: https://github.com/davidhalter/jedi-vim
|
|
||||||
.. _youcompleteme: https://github.com/ycm-core/YouCompleteMe
|
|
||||||
.. _deoplete-jedi: https://github.com/zchee/deoplete-jedi
|
|
||||||
.. _completor.vim: https://github.com/maralla/completor.vim
|
|
||||||
.. _Jedi.el: https://github.com/tkf/emacs-jedi
|
|
||||||
.. _company-mode: https://github.com/syohex/emacs-company-jedi
|
|
||||||
.. _elpy: https://github.com/jorgenschaefer/elpy
|
|
||||||
.. _anaconda-mode: https://github.com/proofit404/anaconda-mode
|
|
||||||
.. _ycmd: https://github.com/abingham/emacs-ycmd
|
|
||||||
.. _sublimejedi: https://github.com/srusskih/SublimeJEDI
|
|
||||||
.. _anaconda: https://github.com/DamnWidget/anaconda
|
|
||||||
.. _wdb: https://github.com/Kozea/wdb
|
|
||||||
.. _TextMate: https://github.com/lawrenceakka/python-jedi.tmbundle
|
|
||||||
.. _Kate: https://kate-editor.org
|
|
||||||
.. _Atom: https://atom.io/
|
|
||||||
.. _autocomplete-python-jedi: https://atom.io/packages/autocomplete-python-jedi
|
|
||||||
.. _GNOME Builder: https://wiki.gnome.org/Apps/Builder
|
|
||||||
.. _Visual Studio Code: https://code.visualstudio.com/
|
|
||||||
.. _gedi: https://github.com/isamert/gedi
|
|
||||||
.. _Eric IDE: https://eric-ide.python-projects.org
|
|
||||||
|
|
||||||
|
|
||||||
.. :changelog:
|
|
||||||
|
|
||||||
Changelog
|
|
||||||
---------
|
|
||||||
|
|
||||||
0.17.0 (2020-04-14)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- Added ``Project`` support. This allows a user to specify which folders Jedi
|
|
||||||
should work with.
|
|
||||||
- Added support for Refactoring. The following refactorings have been
|
|
||||||
implemented: ``Script.rename``, ``Script.inline``,
|
|
||||||
``Script.extract_variable`` and ``Script.extract_function``.
|
|
||||||
- Added ``Script.get_syntax_errors`` to display syntax errors in the current
|
|
||||||
script.
|
|
||||||
- Added code search capabilities both for individual files and projects. The
|
|
||||||
new functions are ``Project.search``, ``Project.complete_search``,
|
|
||||||
``Script.search`` and ``Script.complete_search``.
|
|
||||||
- Added ``Script.help`` to make it easier to display a help window to people.
|
|
||||||
Now returns pydoc information as well for Python keywords/operators. This
|
|
||||||
means that on the class keyword it will now return the docstring of Python's
|
|
||||||
builtin function ``help('class')``.
|
|
||||||
- The API documentation is now way more readable and complete. Check it out
|
|
||||||
under https://jedi.readthedocs.io. A lot of it has been rewritten.
|
|
||||||
- Removed Python 3.4 support
|
|
||||||
- Many bugfixes
|
|
||||||
|
|
||||||
This is likely going to be the last minor version that supports Python 2 and
|
|
||||||
Python3.5. Bugfixes will be provided in 0.17.1+. The next minor/major version
|
|
||||||
will probably be Jedi 1.0.0.
|
|
||||||
|
|
||||||
0.16.0 (2020-01-26)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- **Added** ``Script.get_context`` to get information where you currently are.
|
|
||||||
- Completions/type inference of **Pytest fixtures**.
|
|
||||||
- Tensorflow, Numpy and Pandas completions should now be about **4-10x faster**
|
|
||||||
after the first time they are used.
|
|
||||||
- Dict key completions are working now. e.g. ``d = {1000: 3}; d[10`` will
|
|
||||||
expand to ``1000``.
|
|
||||||
- Completion for "proxies" works now. These are classes that have a
|
|
||||||
``__getattr__(self, name)`` method that does a ``return getattr(x, name)``.
|
|
||||||
after loading them initially.
|
|
||||||
- Goto on a function/attribute in a class now goes to the definition in its
|
|
||||||
super class.
|
|
||||||
- Big **Script API Changes**:
|
|
||||||
- The line and column parameters of ``jedi.Script`` are now deprecated
|
|
||||||
- ``completions`` deprecated, use ``complete`` instead
|
|
||||||
- ``goto_assignments`` deprecated, use ``goto`` instead
|
|
||||||
- ``goto_definitions`` deprecated, use ``infer`` instead
|
|
||||||
- ``call_signatures`` deprecated, use ``get_signatures`` instead
|
|
||||||
- ``usages`` deprecated, use ``get_references`` instead
|
|
||||||
- ``jedi.names`` deprecated, use ``jedi.Script(...).get_names()``
|
|
||||||
- ``BaseName.goto_assignments`` renamed to ``BaseName.goto``
|
|
||||||
- Add follow_imports to ``Name.goto``. Now its signature matches
|
|
||||||
``Script.goto``.
|
|
||||||
- **Python 2 support deprecated**. For this release it is best effort. Python 2
|
|
||||||
has reached the end of its life and now it's just about a smooth transition.
|
|
||||||
Bugs for Python 2 will not be fixed anymore and a third of the tests are
|
|
||||||
already skipped.
|
|
||||||
- Removed ``settings.no_completion_duplicates``. It wasn't tested and nobody
|
|
||||||
was probably using it anyway.
|
|
||||||
- Removed ``settings.use_filesystem_cache`` and
|
|
||||||
``settings.additional_dynamic_modules``, they have no usage anymore. Pretty
|
|
||||||
much nobody was probably using them.
|
|
||||||
|
|
||||||
0.15.2 (2019-12-20)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- Signatures are now detected a lot better
|
|
||||||
- Add fuzzy completions with ``Script(...).completions(fuzzy=True)``
|
|
||||||
- Files bigger than one MB (about 20kLOC) get cropped to avoid getting
|
|
||||||
stuck completely.
|
|
||||||
- Many small Bugfixes
|
|
||||||
- A big refactoring around contexts/values
|
|
||||||
|
|
||||||
0.15.1 (2019-08-13)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- Small bugfix and removal of a print statement
|
|
||||||
|
|
||||||
0.15.0 (2019-08-11)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- Added file path completions, there's a **new** ``Completion.type`` now:
|
|
||||||
``path``. Example: ``'/ho`` -> ``'/home/``
|
|
||||||
- ``*args``/``**kwargs`` resolving. If possible Jedi replaces the parameters
|
|
||||||
with the actual alternatives.
|
|
||||||
- Better support for enums/dataclasses
|
|
||||||
- When using Interpreter, properties are now executed, since a lot of people
|
|
||||||
have complained about this. Discussion in #1299, #1347.
|
|
||||||
|
|
||||||
New APIs:
|
|
||||||
|
|
||||||
- ``Name.get_signatures() -> List[Signature]``. Signatures are similar to
|
|
||||||
``CallSignature``. ``Name.params`` is therefore deprecated.
|
|
||||||
- ``Signature.to_string()`` to format signatures.
|
|
||||||
- ``Signature.params -> List[ParamName]``, ParamName has the
|
|
||||||
following additional attributes ``infer_default()``, ``infer_annotation()``,
|
|
||||||
``to_string()``, and ``kind``.
|
|
||||||
- ``Name.execute() -> List[Name]``, makes it possible to infer
|
|
||||||
return values of functions.
|
|
||||||
|
|
||||||
|
|
||||||
0.14.1 (2019-07-13)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- CallSignature.index should now be working a lot better
|
|
||||||
- A couple of smaller bugfixes
|
|
||||||
|
|
||||||
0.14.0 (2019-06-20)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- Added ``goto_*(prefer_stubs=True)`` as well as ``goto_*(prefer_stubs=True)``
|
|
||||||
- Stubs are used now for type inference
|
|
||||||
- Typeshed is used for better type inference
|
|
||||||
- Reworked Name.full_name, should have more correct return values
|
|
||||||
|
|
||||||
0.13.3 (2019-02-24)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- Fixed an issue with embedded Python, see https://github.com/davidhalter/jedi-vim/issues/870
|
|
||||||
|
|
||||||
0.13.2 (2018-12-15)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- Fixed a bug that led to Jedi spawning a lot of subprocesses.
|
|
||||||
|
|
||||||
0.13.1 (2018-10-02)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- Bugfixes, because tensorflow completions were still slow.
|
|
||||||
|
|
||||||
0.13.0 (2018-10-02)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- A small release. Some bug fixes.
|
|
||||||
- Remove Python 3.3 support. Python 3.3 support has been dropped by the Python
|
|
||||||
foundation.
|
|
||||||
- Default environments are now using the same Python version as the Python
|
|
||||||
process. In 0.12.x, we used to load the latest Python version on the system.
|
|
||||||
- Added ``include_builtins`` as a parameter to usages.
|
|
||||||
- ``goto_assignments`` has a new ``follow_builtin_imports`` parameter that
|
|
||||||
changes the previous behavior slightly.
|
|
||||||
|
|
||||||
0.12.1 (2018-06-30)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- This release forces you to upgrade parso. If you don't, nothing will work
|
|
||||||
anymore. Otherwise changes should be limited to bug fixes. Unfortunately Jedi
|
|
||||||
still uses a few internals of parso that make it hard to keep compatibility
|
|
||||||
over multiple releases. Parso >=0.3.0 is going to be needed.
|
|
||||||
|
|
||||||
0.12.0 (2018-04-15)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- Virtualenv/Environment support
|
|
||||||
- F-String Completion/Goto Support
|
|
||||||
- Cannot crash with segfaults anymore
|
|
||||||
- Cleaned up import logic
|
|
||||||
- Understand async/await and autocomplete it (including async generators)
|
|
||||||
- Better namespace completions
|
|
||||||
- Passing tests for Windows (including CI for Windows)
|
|
||||||
- Remove Python 2.6 support
|
|
||||||
|
|
||||||
0.11.1 (2017-12-14)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- Parso update - the caching layer was broken
|
|
||||||
- Better usages - a lot of internal code was ripped out and improved.
|
|
||||||
|
|
||||||
0.11.0 (2017-09-20)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- Split Jedi's parser into a separate project called ``parso``.
|
|
||||||
- Avoiding side effects in REPL completion.
|
|
||||||
- Numpy docstring support should be much better.
|
|
||||||
- Moved the `settings.*recursion*` away, they are no longer usable.
|
|
||||||
|
|
||||||
0.10.2 (2017-04-05)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- Python Packaging sucks. Some files were not included in 0.10.1.
|
|
||||||
|
|
||||||
0.10.1 (2017-04-05)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- Fixed a few very annoying bugs.
|
|
||||||
- Prepared the parser to be factored out of Jedi.
|
|
||||||
|
|
||||||
0.10.0 (2017-02-03)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- Actual semantic completions for the complete Python syntax.
|
|
||||||
- Basic type inference for ``yield from`` PEP 380.
|
|
||||||
- PEP 484 support (most of the important features of it). Thanks Claude! (@reinhrst)
|
|
||||||
- Added ``get_line_code`` to ``Name`` and ``Completion`` objects.
|
|
||||||
- Completely rewritten the type inference engine.
|
|
||||||
- A new and better parser for (fast) parsing diffs of Python code.
|
|
||||||
|
|
||||||
0.9.0 (2015-04-10)
|
|
||||||
++++++++++++++++++
|
|
||||||
|
|
||||||
- The import logic has been rewritten to look more like Python's. There is now
|
|
||||||
an ``InferState.modules`` import cache, which resembles ``sys.modules``.
|
|
||||||
- Integrated the parser of 2to3. This will make refactoring possible. It will
|
|
||||||
also be possible to check for error messages (like compiling an AST would give)
|
|
||||||
in the future.
|
|
||||||
- With the new parser, the type inference also completely changed. It's now
|
|
||||||
simpler and more readable.
|
|
||||||
- Completely rewritten REPL completion.
|
|
||||||
- Added ``jedi.names``, a command to do static analysis. Thanks to that
|
|
||||||
sourcegraph guys for sponsoring this!
|
|
||||||
- Alpha version of the linter.
|
|
||||||
|
|
||||||
|
|
||||||
0.8.1 (2014-07-23)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- Bugfix release, the last release forgot to include files that improve
|
|
||||||
autocompletion for builtin libraries. Fixed.
|
|
||||||
|
|
||||||
0.8.0 (2014-05-05)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- Memory Consumption for compiled modules (e.g. builtins, sys) has been reduced
|
|
||||||
drastically. Loading times are down as well (it takes basically as long as an
|
|
||||||
import).
|
|
||||||
- REPL completion is starting to become usable.
|
|
||||||
- Various small API changes. Generally this release focuses on stability and
|
|
||||||
refactoring of internal APIs.
|
|
||||||
- Introducing operator precedence, which makes calculating correct Array
|
|
||||||
indices and ``__getattr__`` strings possible.
|
|
||||||
|
|
||||||
0.7.0 (2013-08-09)
|
|
||||||
++++++++++++++++++
|
|
||||||
|
|
||||||
- Switched from LGPL to MIT license.
|
|
||||||
- Added an Interpreter class to the API to make autocompletion in REPL
|
|
||||||
possible.
|
|
||||||
- Added autocompletion support for namespace packages.
|
|
||||||
- Add sith.py, a new random testing method.
|
|
||||||
|
|
||||||
0.6.0 (2013-05-14)
|
|
||||||
++++++++++++++++++
|
|
||||||
|
|
||||||
- Much faster parser with builtin part caching.
|
|
||||||
- A test suite, thanks @tkf.
|
|
||||||
|
|
||||||
0.5 versions (2012)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- Initial development.
|
|
||||||
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
pip
|
|
|
@ -1,507 +0,0 @@
|
||||||
Metadata-Version: 2.0
|
|
||||||
Name: jedi
|
|
||||||
Version: 0.17.0
|
|
||||||
Summary: An autocompletion tool for Python that can be used for text editors.
|
|
||||||
Home-page: https://github.com/davidhalter/jedi
|
|
||||||
Author: David Halter
|
|
||||||
Author-email: davidhalter88@gmail.com
|
|
||||||
Maintainer: David Halter
|
|
||||||
Maintainer-email: davidhalter88@gmail.com
|
|
||||||
License: MIT
|
|
||||||
Keywords: python completion refactoring vim
|
|
||||||
Platform: any
|
|
||||||
Classifier: Development Status :: 4 - Beta
|
|
||||||
Classifier: Environment :: Plugins
|
|
||||||
Classifier: Intended Audience :: Developers
|
|
||||||
Classifier: License :: OSI Approved :: MIT License
|
|
||||||
Classifier: Operating System :: OS Independent
|
|
||||||
Classifier: Programming Language :: Python :: 2
|
|
||||||
Classifier: Programming Language :: Python :: 2.7
|
|
||||||
Classifier: Programming Language :: Python :: 3
|
|
||||||
Classifier: Programming Language :: Python :: 3.5
|
|
||||||
Classifier: Programming Language :: Python :: 3.6
|
|
||||||
Classifier: Programming Language :: Python :: 3.7
|
|
||||||
Classifier: Programming Language :: Python :: 3.8
|
|
||||||
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
||||||
Classifier: Topic :: Text Editors :: Integrated Development Environments (IDE)
|
|
||||||
Classifier: Topic :: Utilities
|
|
||||||
Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*
|
|
||||||
Provides-Extra: qa
|
|
||||||
Provides-Extra: testing
|
|
||||||
Requires-Dist: parso (>=0.7.0)
|
|
||||||
Provides-Extra: qa
|
|
||||||
Requires-Dist: flake8 (==3.7.9); extra == 'qa'
|
|
||||||
Provides-Extra: testing
|
|
||||||
Requires-Dist: colorama; extra == 'testing'
|
|
||||||
Requires-Dist: docopt; extra == 'testing'
|
|
||||||
Requires-Dist: pytest (<5.0.0,>=3.9.0); extra == 'testing'
|
|
||||||
|
|
||||||
####################################################################################
|
|
||||||
Jedi - an awesome autocompletion, static analysis and refactoring library for Python
|
|
||||||
####################################################################################
|
|
||||||
|
|
||||||
.. image:: http://isitmaintained.com/badge/open/davidhalter/jedi.svg
|
|
||||||
:target: https://github.com/davidhalter/jedi/issues
|
|
||||||
:alt: The percentage of open issues and pull requests
|
|
||||||
|
|
||||||
.. image:: http://isitmaintained.com/badge/resolution/davidhalter/jedi.svg
|
|
||||||
:target: https://github.com/davidhalter/jedi/issues
|
|
||||||
:alt: The resolution time is the median time an issue or pull request stays open.
|
|
||||||
|
|
||||||
.. image:: https://travis-ci.org/davidhalter/jedi.svg?branch=master
|
|
||||||
:target: https://travis-ci.org/davidhalter/jedi
|
|
||||||
:alt: Linux Tests
|
|
||||||
|
|
||||||
.. image:: https://ci.appveyor.com/api/projects/status/mgva3bbawyma1new/branch/master?svg=true
|
|
||||||
:target: https://ci.appveyor.com/project/davidhalter/jedi/branch/master
|
|
||||||
:alt: Windows Tests
|
|
||||||
|
|
||||||
.. image:: https://coveralls.io/repos/davidhalter/jedi/badge.svg?branch=master
|
|
||||||
:target: https://coveralls.io/r/davidhalter/jedi
|
|
||||||
:alt: Coverage status
|
|
||||||
|
|
||||||
|
|
||||||
Jedi is a static analysis tool for Python that is typically used in
|
|
||||||
IDEs/editors plugins. Jedi has a focus on autocompletion and goto
|
|
||||||
functionality. Other features include refactoring, code search and finding
|
|
||||||
references.
|
|
||||||
|
|
||||||
Jedi has a simple API to work with. There is a reference implementation as a
|
|
||||||
`VIM-Plugin <https://github.com/davidhalter/jedi-vim>`_. Autocompletion in your
|
|
||||||
REPL is also possible, IPython uses it natively and for the CPython REPL you
|
|
||||||
can install it. Jedi is well tested and bugs should be rare.
|
|
||||||
|
|
||||||
Jedi can currently be used with the following editors/projects:
|
|
||||||
|
|
||||||
- Vim (jedi-vim_, YouCompleteMe_, deoplete-jedi_, completor.vim_)
|
|
||||||
- `Visual Studio Code`_ (via `Python Extension <https://marketplace.visualstudio.com/items?itemName=ms-python.python>`_)
|
|
||||||
- Emacs (Jedi.el_, company-mode_, elpy_, anaconda-mode_, ycmd_)
|
|
||||||
- Sublime Text (SublimeJEDI_ [ST2 + ST3], anaconda_ [only ST3])
|
|
||||||
- TextMate_ (Not sure if it's actually working)
|
|
||||||
- Kate_ version 4.13+ supports it natively, you have to enable it, though. [`see
|
|
||||||
<https://projects.kde.org/projects/kde/applications/kate/repository/show?rev=KDE%2F4.13>`_]
|
|
||||||
- Atom_ (autocomplete-python-jedi_)
|
|
||||||
- `GNOME Builder`_ (with support for GObject Introspection)
|
|
||||||
- Gedit (gedi_)
|
|
||||||
- wdb_ - Web Debugger
|
|
||||||
- `Eric IDE`_ (Available as a plugin)
|
|
||||||
- `IPython 6.0.0+ <https://ipython.readthedocs.io/en/stable/whatsnew/version6.html>`_
|
|
||||||
|
|
||||||
and many more!
|
|
||||||
|
|
||||||
Here are some pictures taken from jedi-vim_:
|
|
||||||
|
|
||||||
.. image:: https://github.com/davidhalter/jedi/raw/master/docs/_screenshots/screenshot_complete.png
|
|
||||||
|
|
||||||
Completion for almost anything:
|
|
||||||
|
|
||||||
.. image:: https://github.com/davidhalter/jedi/raw/master/docs/_screenshots/screenshot_function.png
|
|
||||||
|
|
||||||
Documentation:
|
|
||||||
|
|
||||||
.. image:: https://github.com/davidhalter/jedi/raw/master/docs/_screenshots/screenshot_pydoc.png
|
|
||||||
|
|
||||||
|
|
||||||
Get the latest version from `github <https://github.com/davidhalter/jedi>`_
|
|
||||||
(master branch should always be kind of stable/working).
|
|
||||||
|
|
||||||
Docs are available at `https://jedi.readthedocs.org/en/latest/
|
|
||||||
<https://jedi.readthedocs.org/en/latest/>`_. Pull requests with enhancements
|
|
||||||
and/or fixes are awesome and most welcome. Jedi uses `semantic versioning
|
|
||||||
<https://semver.org/>`_.
|
|
||||||
|
|
||||||
If you want to stay up-to-date (News / RFCs), please subscribe to this `github
|
|
||||||
thread <https://github.com/davidhalter/jedi/issues/1063>`_.:
|
|
||||||
|
|
||||||
Issues & Questions
|
|
||||||
==================
|
|
||||||
|
|
||||||
You can file issues and questions in the `issue tracker
|
|
||||||
<https://github.com/davidhalter/jedi/>`. Alternatively you can also ask on
|
|
||||||
`Stack Overflow <https://stackoverflow.com/questions/tagged/python-jedi>`_ with
|
|
||||||
the label ``python-jedi``.
|
|
||||||
|
|
||||||
Installation
|
|
||||||
============
|
|
||||||
|
|
||||||
`Check out the docs <https://jedi.readthedocs.org/en/latest/docs/installation.html>`_.
|
|
||||||
|
|
||||||
Features and Limitations
|
|
||||||
========================
|
|
||||||
|
|
||||||
Jedi's features are listed here:
|
|
||||||
`Features <https://jedi.readthedocs.org/en/latest/docs/features.html>`_.
|
|
||||||
|
|
||||||
You can run Jedi on CPython 2.7 or 3.5+ but it should also
|
|
||||||
understand code that is older than those versions. Additionally you should be
|
|
||||||
able to use `Virtualenvs <https://jedi.readthedocs.org/en/latest/docs/api.html#environments>`_
|
|
||||||
very well.
|
|
||||||
|
|
||||||
Tips on how to use Jedi efficiently can be found `here
|
|
||||||
<https://jedi.readthedocs.org/en/latest/docs/features.html#recipes>`_.
|
|
||||||
|
|
||||||
API
|
|
||||||
---
|
|
||||||
|
|
||||||
You can find a comprehensive documentation for the
|
|
||||||
`API here <https://jedi.readthedocs.org/en/latest/docs/api.html>`_.
|
|
||||||
|
|
||||||
Autocompletion / Goto / Documentation
|
|
||||||
-------------------------------------
|
|
||||||
|
|
||||||
There are the following commands:
|
|
||||||
|
|
||||||
- ``jedi.Script.goto``
|
|
||||||
- ``jedi.Script.infer``
|
|
||||||
- ``jedi.Script.help``
|
|
||||||
- ``jedi.Script.complete``
|
|
||||||
- ``jedi.Script.get_references``
|
|
||||||
- ``jedi.Script.get_signatures``
|
|
||||||
- ``jedi.Script.get_context``
|
|
||||||
|
|
||||||
The returned objects are very powerful and are really all you might need.
|
|
||||||
|
|
||||||
Autocompletion in your REPL (IPython, etc.)
|
|
||||||
-------------------------------------------
|
|
||||||
|
|
||||||
Jedi is a dependency of IPython. Autocompletion in IPython with Jedi is
|
|
||||||
therefore possible without additional configuration.
|
|
||||||
|
|
||||||
Here is an `example video <https://vimeo.com/122332037>`_ how REPL completion
|
|
||||||
can look like.
|
|
||||||
For the ``python`` shell you can enable tab completion in a `REPL
|
|
||||||
<https://jedi.readthedocs.org/en/latest/docs/usage.html#tab-completion-in-the-python-shell>`_.
|
|
||||||
|
|
||||||
Static Analysis
|
|
||||||
---------------
|
|
||||||
|
|
||||||
For a lot of forms of static analysis, you can try to use
|
|
||||||
``jedi.Script(...).get_names``. It will return a list of names that you can
|
|
||||||
then filter and work with. There is also a way to list the syntax errors in a
|
|
||||||
file: ``jedi.Script.get_syntax_errors``.
|
|
||||||
|
|
||||||
|
|
||||||
Refactoring
|
|
||||||
-----------
|
|
||||||
|
|
||||||
Jedi supports the following refactorings:
|
|
||||||
|
|
||||||
- ``jedi.Script.inline``
|
|
||||||
- ``jedi.Script.rename``
|
|
||||||
- ``jedi.Script.extract_function``
|
|
||||||
- ``jedi.Script.extract_variable``
|
|
||||||
|
|
||||||
Code Search
|
|
||||||
-----------
|
|
||||||
|
|
||||||
There is support for module search with ``jedi.Script.search``, and project
|
|
||||||
search for ``jedi.Project.search``. The way to search is either by providing a
|
|
||||||
name like ``foo`` or by using dotted syntax like ``foo.bar``. Additionally you
|
|
||||||
can provide the API type like ``class foo.bar.Bar``. There are also the
|
|
||||||
functions ``jedi.Script.complete_search`` and ``jedi.Project.complete_search``.
|
|
||||||
|
|
||||||
Development
|
|
||||||
===========
|
|
||||||
|
|
||||||
There's a pretty good and extensive `development documentation
|
|
||||||
<https://jedi.readthedocs.org/en/latest/docs/development.html>`_.
|
|
||||||
|
|
||||||
Testing
|
|
||||||
=======
|
|
||||||
|
|
||||||
The test suite uses ``pytest``::
|
|
||||||
|
|
||||||
pip install pytest
|
|
||||||
|
|
||||||
If you want to test only a specific Python version (e.g. Python 3.8), it is as
|
|
||||||
easy as::
|
|
||||||
|
|
||||||
python3.8 -m pytest
|
|
||||||
|
|
||||||
For more detailed information visit the `testing documentation
|
|
||||||
<https://jedi.readthedocs.org/en/latest/docs/testing.html>`_.
|
|
||||||
|
|
||||||
Acknowledgements
|
|
||||||
================
|
|
||||||
|
|
||||||
Thanks a lot to all the
|
|
||||||
`contributors <https://jedi.readthedocs.org/en/latest/docs/acknowledgements.html>`_!
|
|
||||||
|
|
||||||
|
|
||||||
.. _jedi-vim: https://github.com/davidhalter/jedi-vim
|
|
||||||
.. _youcompleteme: https://github.com/ycm-core/YouCompleteMe
|
|
||||||
.. _deoplete-jedi: https://github.com/zchee/deoplete-jedi
|
|
||||||
.. _completor.vim: https://github.com/maralla/completor.vim
|
|
||||||
.. _Jedi.el: https://github.com/tkf/emacs-jedi
|
|
||||||
.. _company-mode: https://github.com/syohex/emacs-company-jedi
|
|
||||||
.. _elpy: https://github.com/jorgenschaefer/elpy
|
|
||||||
.. _anaconda-mode: https://github.com/proofit404/anaconda-mode
|
|
||||||
.. _ycmd: https://github.com/abingham/emacs-ycmd
|
|
||||||
.. _sublimejedi: https://github.com/srusskih/SublimeJEDI
|
|
||||||
.. _anaconda: https://github.com/DamnWidget/anaconda
|
|
||||||
.. _wdb: https://github.com/Kozea/wdb
|
|
||||||
.. _TextMate: https://github.com/lawrenceakka/python-jedi.tmbundle
|
|
||||||
.. _Kate: https://kate-editor.org
|
|
||||||
.. _Atom: https://atom.io/
|
|
||||||
.. _autocomplete-python-jedi: https://atom.io/packages/autocomplete-python-jedi
|
|
||||||
.. _GNOME Builder: https://wiki.gnome.org/Apps/Builder
|
|
||||||
.. _Visual Studio Code: https://code.visualstudio.com/
|
|
||||||
.. _gedi: https://github.com/isamert/gedi
|
|
||||||
.. _Eric IDE: https://eric-ide.python-projects.org
|
|
||||||
|
|
||||||
|
|
||||||
.. :changelog:
|
|
||||||
|
|
||||||
Changelog
|
|
||||||
---------
|
|
||||||
|
|
||||||
0.17.0 (2020-04-14)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- Added ``Project`` support. This allows a user to specify which folders Jedi
|
|
||||||
should work with.
|
|
||||||
- Added support for Refactoring. The following refactorings have been
|
|
||||||
implemented: ``Script.rename``, ``Script.inline``,
|
|
||||||
``Script.extract_variable`` and ``Script.extract_function``.
|
|
||||||
- Added ``Script.get_syntax_errors`` to display syntax errors in the current
|
|
||||||
script.
|
|
||||||
- Added code search capabilities both for individual files and projects. The
|
|
||||||
new functions are ``Project.search``, ``Project.complete_search``,
|
|
||||||
``Script.search`` and ``Script.complete_search``.
|
|
||||||
- Added ``Script.help`` to make it easier to display a help window to people.
|
|
||||||
Now returns pydoc information as well for Python keywords/operators. This
|
|
||||||
means that on the class keyword it will now return the docstring of Python's
|
|
||||||
builtin function ``help('class')``.
|
|
||||||
- The API documentation is now way more readable and complete. Check it out
|
|
||||||
under https://jedi.readthedocs.io. A lot of it has been rewritten.
|
|
||||||
- Removed Python 3.4 support
|
|
||||||
- Many bugfixes
|
|
||||||
|
|
||||||
This is likely going to be the last minor version that supports Python 2 and
|
|
||||||
Python3.5. Bugfixes will be provided in 0.17.1+. The next minor/major version
|
|
||||||
will probably be Jedi 1.0.0.
|
|
||||||
|
|
||||||
0.16.0 (2020-01-26)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- **Added** ``Script.get_context`` to get information where you currently are.
|
|
||||||
- Completions/type inference of **Pytest fixtures**.
|
|
||||||
- Tensorflow, Numpy and Pandas completions should now be about **4-10x faster**
|
|
||||||
after the first time they are used.
|
|
||||||
- Dict key completions are working now. e.g. ``d = {1000: 3}; d[10`` will
|
|
||||||
expand to ``1000``.
|
|
||||||
- Completion for "proxies" works now. These are classes that have a
|
|
||||||
``__getattr__(self, name)`` method that does a ``return getattr(x, name)``.
|
|
||||||
after loading them initially.
|
|
||||||
- Goto on a function/attribute in a class now goes to the definition in its
|
|
||||||
super class.
|
|
||||||
- Big **Script API Changes**:
|
|
||||||
- The line and column parameters of ``jedi.Script`` are now deprecated
|
|
||||||
- ``completions`` deprecated, use ``complete`` instead
|
|
||||||
- ``goto_assignments`` deprecated, use ``goto`` instead
|
|
||||||
- ``goto_definitions`` deprecated, use ``infer`` instead
|
|
||||||
- ``call_signatures`` deprecated, use ``get_signatures`` instead
|
|
||||||
- ``usages`` deprecated, use ``get_references`` instead
|
|
||||||
- ``jedi.names`` deprecated, use ``jedi.Script(...).get_names()``
|
|
||||||
- ``BaseName.goto_assignments`` renamed to ``BaseName.goto``
|
|
||||||
- Add follow_imports to ``Name.goto``. Now its signature matches
|
|
||||||
``Script.goto``.
|
|
||||||
- **Python 2 support deprecated**. For this release it is best effort. Python 2
|
|
||||||
has reached the end of its life and now it's just about a smooth transition.
|
|
||||||
Bugs for Python 2 will not be fixed anymore and a third of the tests are
|
|
||||||
already skipped.
|
|
||||||
- Removed ``settings.no_completion_duplicates``. It wasn't tested and nobody
|
|
||||||
was probably using it anyway.
|
|
||||||
- Removed ``settings.use_filesystem_cache`` and
|
|
||||||
``settings.additional_dynamic_modules``, they have no usage anymore. Pretty
|
|
||||||
much nobody was probably using them.
|
|
||||||
|
|
||||||
0.15.2 (2019-12-20)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- Signatures are now detected a lot better
|
|
||||||
- Add fuzzy completions with ``Script(...).completions(fuzzy=True)``
|
|
||||||
- Files bigger than one MB (about 20kLOC) get cropped to avoid getting
|
|
||||||
stuck completely.
|
|
||||||
- Many small Bugfixes
|
|
||||||
- A big refactoring around contexts/values
|
|
||||||
|
|
||||||
0.15.1 (2019-08-13)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- Small bugfix and removal of a print statement
|
|
||||||
|
|
||||||
0.15.0 (2019-08-11)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- Added file path completions, there's a **new** ``Completion.type`` now:
|
|
||||||
``path``. Example: ``'/ho`` -> ``'/home/``
|
|
||||||
- ``*args``/``**kwargs`` resolving. If possible Jedi replaces the parameters
|
|
||||||
with the actual alternatives.
|
|
||||||
- Better support for enums/dataclasses
|
|
||||||
- When using Interpreter, properties are now executed, since a lot of people
|
|
||||||
have complained about this. Discussion in #1299, #1347.
|
|
||||||
|
|
||||||
New APIs:
|
|
||||||
|
|
||||||
- ``Name.get_signatures() -> List[Signature]``. Signatures are similar to
|
|
||||||
``CallSignature``. ``Name.params`` is therefore deprecated.
|
|
||||||
- ``Signature.to_string()`` to format signatures.
|
|
||||||
- ``Signature.params -> List[ParamName]``, ParamName has the
|
|
||||||
following additional attributes ``infer_default()``, ``infer_annotation()``,
|
|
||||||
``to_string()``, and ``kind``.
|
|
||||||
- ``Name.execute() -> List[Name]``, makes it possible to infer
|
|
||||||
return values of functions.
|
|
||||||
|
|
||||||
|
|
||||||
0.14.1 (2019-07-13)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- CallSignature.index should now be working a lot better
|
|
||||||
- A couple of smaller bugfixes
|
|
||||||
|
|
||||||
0.14.0 (2019-06-20)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- Added ``goto_*(prefer_stubs=True)`` as well as ``goto_*(prefer_stubs=True)``
|
|
||||||
- Stubs are used now for type inference
|
|
||||||
- Typeshed is used for better type inference
|
|
||||||
- Reworked Name.full_name, should have more correct return values
|
|
||||||
|
|
||||||
0.13.3 (2019-02-24)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- Fixed an issue with embedded Python, see https://github.com/davidhalter/jedi-vim/issues/870
|
|
||||||
|
|
||||||
0.13.2 (2018-12-15)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- Fixed a bug that led to Jedi spawning a lot of subprocesses.
|
|
||||||
|
|
||||||
0.13.1 (2018-10-02)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- Bugfixes, because tensorflow completions were still slow.
|
|
||||||
|
|
||||||
0.13.0 (2018-10-02)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- A small release. Some bug fixes.
|
|
||||||
- Remove Python 3.3 support. Python 3.3 support has been dropped by the Python
|
|
||||||
foundation.
|
|
||||||
- Default environments are now using the same Python version as the Python
|
|
||||||
process. In 0.12.x, we used to load the latest Python version on the system.
|
|
||||||
- Added ``include_builtins`` as a parameter to usages.
|
|
||||||
- ``goto_assignments`` has a new ``follow_builtin_imports`` parameter that
|
|
||||||
changes the previous behavior slightly.
|
|
||||||
|
|
||||||
0.12.1 (2018-06-30)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- This release forces you to upgrade parso. If you don't, nothing will work
|
|
||||||
anymore. Otherwise changes should be limited to bug fixes. Unfortunately Jedi
|
|
||||||
still uses a few internals of parso that make it hard to keep compatibility
|
|
||||||
over multiple releases. Parso >=0.3.0 is going to be needed.
|
|
||||||
|
|
||||||
0.12.0 (2018-04-15)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- Virtualenv/Environment support
|
|
||||||
- F-String Completion/Goto Support
|
|
||||||
- Cannot crash with segfaults anymore
|
|
||||||
- Cleaned up import logic
|
|
||||||
- Understand async/await and autocomplete it (including async generators)
|
|
||||||
- Better namespace completions
|
|
||||||
- Passing tests for Windows (including CI for Windows)
|
|
||||||
- Remove Python 2.6 support
|
|
||||||
|
|
||||||
0.11.1 (2017-12-14)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- Parso update - the caching layer was broken
|
|
||||||
- Better usages - a lot of internal code was ripped out and improved.
|
|
||||||
|
|
||||||
0.11.0 (2017-09-20)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- Split Jedi's parser into a separate project called ``parso``.
|
|
||||||
- Avoiding side effects in REPL completion.
|
|
||||||
- Numpy docstring support should be much better.
|
|
||||||
- Moved the `settings.*recursion*` away, they are no longer usable.
|
|
||||||
|
|
||||||
0.10.2 (2017-04-05)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- Python Packaging sucks. Some files were not included in 0.10.1.
|
|
||||||
|
|
||||||
0.10.1 (2017-04-05)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- Fixed a few very annoying bugs.
|
|
||||||
- Prepared the parser to be factored out of Jedi.
|
|
||||||
|
|
||||||
0.10.0 (2017-02-03)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- Actual semantic completions for the complete Python syntax.
|
|
||||||
- Basic type inference for ``yield from`` PEP 380.
|
|
||||||
- PEP 484 support (most of the important features of it). Thanks Claude! (@reinhrst)
|
|
||||||
- Added ``get_line_code`` to ``Name`` and ``Completion`` objects.
|
|
||||||
- Completely rewritten the type inference engine.
|
|
||||||
- A new and better parser for (fast) parsing diffs of Python code.
|
|
||||||
|
|
||||||
0.9.0 (2015-04-10)
|
|
||||||
++++++++++++++++++
|
|
||||||
|
|
||||||
- The import logic has been rewritten to look more like Python's. There is now
|
|
||||||
an ``InferState.modules`` import cache, which resembles ``sys.modules``.
|
|
||||||
- Integrated the parser of 2to3. This will make refactoring possible. It will
|
|
||||||
also be possible to check for error messages (like compiling an AST would give)
|
|
||||||
in the future.
|
|
||||||
- With the new parser, the type inference also completely changed. It's now
|
|
||||||
simpler and more readable.
|
|
||||||
- Completely rewritten REPL completion.
|
|
||||||
- Added ``jedi.names``, a command to do static analysis. Thanks to that
|
|
||||||
sourcegraph guys for sponsoring this!
|
|
||||||
- Alpha version of the linter.
|
|
||||||
|
|
||||||
|
|
||||||
0.8.1 (2014-07-23)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- Bugfix release, the last release forgot to include files that improve
|
|
||||||
autocompletion for builtin libraries. Fixed.
|
|
||||||
|
|
||||||
0.8.0 (2014-05-05)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- Memory Consumption for compiled modules (e.g. builtins, sys) has been reduced
|
|
||||||
drastically. Loading times are down as well (it takes basically as long as an
|
|
||||||
import).
|
|
||||||
- REPL completion is starting to become usable.
|
|
||||||
- Various small API changes. Generally this release focuses on stability and
|
|
||||||
refactoring of internal APIs.
|
|
||||||
- Introducing operator precedence, which makes calculating correct Array
|
|
||||||
indices and ``__getattr__`` strings possible.
|
|
||||||
|
|
||||||
0.7.0 (2013-08-09)
|
|
||||||
++++++++++++++++++
|
|
||||||
|
|
||||||
- Switched from LGPL to MIT license.
|
|
||||||
- Added an Interpreter class to the API to make autocompletion in REPL
|
|
||||||
possible.
|
|
||||||
- Added autocompletion support for namespace packages.
|
|
||||||
- Add sith.py, a new random testing method.
|
|
||||||
|
|
||||||
0.6.0 (2013-05-14)
|
|
||||||
++++++++++++++++++
|
|
||||||
|
|
||||||
- Much faster parser with builtin part caching.
|
|
||||||
- A test suite, thanks @tkf.
|
|
||||||
|
|
||||||
0.5 versions (2012)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
- Initial development.
|
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +0,0 @@
|
||||||
Wheel-Version: 1.0
|
|
||||||
Generator: bdist_wheel (0.29.0)
|
|
||||||
Root-Is-Purelib: true
|
|
||||||
Tag: py2-none-any
|
|
||||||
Tag: py3-none-any
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
{"classifiers": ["Development Status :: 4 - Beta", "Environment :: Plugins", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Text Editors :: Integrated Development Environments (IDE)", "Topic :: Utilities"], "extensions": {"python.details": {"contacts": [{"email": "davidhalter88@gmail.com", "name": "David Halter", "role": "author"}, {"email": "davidhalter88@gmail.com", "name": "David Halter", "role": "maintainer"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "https://github.com/davidhalter/jedi"}}}, "extras": ["qa", "testing"], "generator": "bdist_wheel (0.29.0)", "keywords": ["python", "completion", "refactoring", "vim"], "license": "MIT", "metadata_version": "2.0", "name": "jedi", "platform": "any", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*", "run_requires": [{"extra": "testing", "requires": ["colorama", "docopt", "pytest (<5.0.0,>=3.9.0)"]}, {"extra": "qa", "requires": ["flake8 (==3.7.9)"]}, {"requires": ["parso (>=0.7.0)"]}], "summary": "An autocompletion tool for Python that can be used for text editors.", "version": "0.17.0"}
|
|
|
@ -1 +0,0 @@
|
||||||
jedi
|
|
|
@ -27,7 +27,7 @@ ad
|
||||||
load
|
load
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__version__ = '0.17.0'
|
__version__ = '0.17.1'
|
||||||
|
|
||||||
from jedi.api import Script, Interpreter, set_debug_function, \
|
from jedi.api import Script, Interpreter, set_debug_function, \
|
||||||
preload_module, names
|
preload_module, names
|
||||||
|
|
|
@ -44,20 +44,29 @@ def _complete():
|
||||||
import jedi
|
import jedi
|
||||||
import pdb
|
import pdb
|
||||||
|
|
||||||
|
if '-d' in sys.argv:
|
||||||
|
sys.argv.remove('-d')
|
||||||
|
jedi.set_debug_function()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
for c in jedi.Script(sys.argv[2]).complete():
|
completions = jedi.Script(sys.argv[2]).complete()
|
||||||
|
for c in completions:
|
||||||
c.docstring()
|
c.docstring()
|
||||||
c.type
|
c.type
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(repr(e))
|
||||||
pdb.post_mortem()
|
pdb.post_mortem()
|
||||||
|
else:
|
||||||
|
print(completions)
|
||||||
|
|
||||||
|
|
||||||
if len(sys.argv) == 2 and sys.argv[1] == 'repl':
|
if len(sys.argv) == 2 and sys.argv[1] == 'repl':
|
||||||
# don't want to use __main__ only for repl yet, maybe we want to use it for
|
# don't want to use __main__ only for repl yet, maybe we want to use it for
|
||||||
# something else. So just use the keyword ``repl`` for now.
|
# something else. So just use the keyword ``repl`` for now.
|
||||||
print(join(dirname(abspath(__file__)), 'api', 'replstartup.py'))
|
print(join(dirname(abspath(__file__)), 'api', 'replstartup.py'))
|
||||||
elif len(sys.argv) > 1 and sys.argv[1] == 'linter':
|
elif len(sys.argv) > 1 and sys.argv[1] == '_linter':
|
||||||
_start_linter()
|
_start_linter()
|
||||||
elif len(sys.argv) > 1 and sys.argv[1] == '_complete':
|
elif len(sys.argv) > 1 and sys.argv[1] == '_complete':
|
||||||
_complete()
|
_complete()
|
||||||
|
else:
|
||||||
|
print('Command not implemented: %s' % sys.argv[1])
|
||||||
|
|
|
@ -339,6 +339,13 @@ try:
|
||||||
except NameError:
|
except NameError:
|
||||||
PermissionError = IOError
|
PermissionError = IOError
|
||||||
|
|
||||||
|
try:
|
||||||
|
NotADirectoryError = NotADirectoryError
|
||||||
|
except NameError:
|
||||||
|
class NotADirectoryError(Exception):
|
||||||
|
# Don't implement this for Python 2 anymore.
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def no_unicode_pprint(dct):
|
def no_unicode_pprint(dct):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -97,7 +97,7 @@ class Script(object):
|
||||||
an issue for people that do more complex stuff with Jedi.
|
an issue for people that do more complex stuff with Jedi.
|
||||||
|
|
||||||
This is purely a performance optimization and works pretty well for all
|
This is purely a performance optimization and works pretty well for all
|
||||||
typical usages, however consider to turn the setting of if it causes
|
typical usages, however consider to turn the setting off if it causes
|
||||||
you problems. See also
|
you problems. See also
|
||||||
`this discussion <https://github.com/davidhalter/jedi/issues/1240>`_.
|
`this discussion <https://github.com/davidhalter/jedi/issues/1240>`_.
|
||||||
|
|
||||||
|
@ -128,15 +128,6 @@ class Script(object):
|
||||||
# An empty path (also empty string) should always result in no path.
|
# An empty path (also empty string) should always result in no path.
|
||||||
self.path = os.path.abspath(path) if path else None
|
self.path = os.path.abspath(path) if path else None
|
||||||
|
|
||||||
# TODO deprecate and remove sys_path from the Script API.
|
|
||||||
if sys_path is not None:
|
|
||||||
project._sys_path = sys_path
|
|
||||||
warnings.warn(
|
|
||||||
"Deprecated since version 0.17.0. Use the project API instead, "
|
|
||||||
"which means Script(project=Project(dir, sys_path=sys_path)) instead.",
|
|
||||||
DeprecationWarning,
|
|
||||||
stacklevel=2
|
|
||||||
)
|
|
||||||
if encoding is None:
|
if encoding is None:
|
||||||
encoding = 'utf-8'
|
encoding = 'utf-8'
|
||||||
else:
|
else:
|
||||||
|
@ -180,6 +171,15 @@ class Script(object):
|
||||||
project = get_default_project(
|
project = get_default_project(
|
||||||
os.path.dirname(self.path) if path else None
|
os.path.dirname(self.path) if path else None
|
||||||
)
|
)
|
||||||
|
# TODO deprecate and remove sys_path from the Script API.
|
||||||
|
if sys_path is not None:
|
||||||
|
project._sys_path = sys_path
|
||||||
|
warnings.warn(
|
||||||
|
"Deprecated since version 0.17.0. Use the project API instead, "
|
||||||
|
"which means Script(project=Project(dir, sys_path=sys_path)) instead.",
|
||||||
|
DeprecationWarning,
|
||||||
|
stacklevel=2
|
||||||
|
)
|
||||||
|
|
||||||
self._inference_state = InferenceState(
|
self._inference_state = InferenceState(
|
||||||
project, environment=environment, script_path=self.path
|
project, environment=environment, script_path=self.path
|
||||||
|
@ -472,9 +472,20 @@ class Script(object):
|
||||||
if definitions:
|
if definitions:
|
||||||
return definitions
|
return definitions
|
||||||
leaf = self._module_node.get_leaf_for_position((line, column))
|
leaf = self._module_node.get_leaf_for_position((line, column))
|
||||||
if leaf.type in ('keyword', 'operator', 'error_leaf'):
|
if leaf is not None and leaf.type in ('keyword', 'operator', 'error_leaf'):
|
||||||
reserved = self._inference_state.grammar._pgen_grammar.reserved_syntax_strings.keys()
|
def need_pydoc():
|
||||||
if leaf.value in reserved:
|
if leaf.value in ('(', ')', '[', ']'):
|
||||||
|
if leaf.parent.type == 'trailer':
|
||||||
|
return False
|
||||||
|
if leaf.parent.type == 'atom':
|
||||||
|
return False
|
||||||
|
grammar = self._inference_state.grammar
|
||||||
|
# This parso stuff is not public, but since I control it, this
|
||||||
|
# is fine :-) ~dave
|
||||||
|
reserved = grammar._pgen_grammar.reserved_syntax_strings.keys()
|
||||||
|
return leaf.value in reserved
|
||||||
|
|
||||||
|
if need_pydoc():
|
||||||
name = KeywordName(self._inference_state, leaf.value)
|
name = KeywordName(self._inference_state, leaf.value)
|
||||||
return [classes.Name(self._inference_state, name)]
|
return [classes.Name(self._inference_state, name)]
|
||||||
return []
|
return []
|
||||||
|
@ -494,21 +505,25 @@ class Script(object):
|
||||||
quite hard to do for Jedi, if it is too complicated, Jedi will stop
|
quite hard to do for Jedi, if it is too complicated, Jedi will stop
|
||||||
searching.
|
searching.
|
||||||
|
|
||||||
:param include_builtins: Default True, checks if a reference is a
|
:param include_builtins: Default ``True``. If ``False``, checks if a reference
|
||||||
builtin (e.g. ``sys``) and in that case does not return it.
|
is a builtin (e.g. ``sys``) and in that case does not return it.
|
||||||
|
:param scope: Default ``'project'``. If ``'file'``, include references in
|
||||||
|
the current module only.
|
||||||
:rtype: list of :class:`.Name`
|
:rtype: list of :class:`.Name`
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def _references(include_builtins=True):
|
def _references(include_builtins=True, scope='project'):
|
||||||
|
if scope not in ('project', 'file'):
|
||||||
|
raise ValueError('Only the scopes "file" and "project" are allowed')
|
||||||
tree_name = self._module_node.get_name_of_position((line, column))
|
tree_name = self._module_node.get_name_of_position((line, column))
|
||||||
if tree_name is None:
|
if tree_name is None:
|
||||||
# Must be syntax
|
# Must be syntax
|
||||||
return []
|
return []
|
||||||
|
|
||||||
names = find_references(self._get_module_context(), tree_name)
|
names = find_references(self._get_module_context(), tree_name, scope == 'file')
|
||||||
|
|
||||||
definitions = [classes.Name(self._inference_state, n) for n in names]
|
definitions = [classes.Name(self._inference_state, n) for n in names]
|
||||||
if not include_builtins:
|
if not include_builtins or scope == 'file':
|
||||||
definitions = [d for d in definitions if not d.in_builtin_module()]
|
definitions = [d for d in definitions if not d.in_builtin_module()]
|
||||||
return helpers.sorted_definitions(definitions)
|
return helpers.sorted_definitions(definitions)
|
||||||
return _references(**kwargs)
|
return _references(**kwargs)
|
||||||
|
@ -748,10 +763,11 @@ class Script(object):
|
||||||
global_var = 3
|
global_var = 3
|
||||||
|
|
||||||
def bar(foo):
|
def bar(foo):
|
||||||
return foo + 1 + global_var
|
return int(foo + 1 + global_var)
|
||||||
|
|
||||||
def x(foo):
|
def x():
|
||||||
x = int(bar(foo))
|
foo = 3.1
|
||||||
|
x = bar(foo)
|
||||||
|
|
||||||
:param new_name: The expression under the cursor will be replaced with
|
:param new_name: The expression under the cursor will be replaced with
|
||||||
a function with this name.
|
a function with this name.
|
||||||
|
|
|
@ -25,6 +25,7 @@ from jedi.inference.utils import unite
|
||||||
from jedi.cache import memoize_method
|
from jedi.cache import memoize_method
|
||||||
from jedi.inference import imports
|
from jedi.inference import imports
|
||||||
from jedi.inference.imports import ImportName
|
from jedi.inference.imports import ImportName
|
||||||
|
from jedi.inference.compiled.mixed import MixedName
|
||||||
from jedi.inference.gradual.typeshed import StubModuleValue
|
from jedi.inference.gradual.typeshed import StubModuleValue
|
||||||
from jedi.inference.gradual.conversion import convert_names, convert_values
|
from jedi.inference.gradual.conversion import convert_names, convert_values
|
||||||
from jedi.inference.base_value import ValueSet
|
from jedi.inference.base_value import ValueSet
|
||||||
|
@ -94,7 +95,11 @@ class BaseName(object):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def module_path(self):
|
def module_path(self):
|
||||||
"""Shows the file path of a module. e.g. ``/usr/lib/python2.7/os.py``"""
|
"""
|
||||||
|
Shows the file path of a module. e.g. ``/usr/lib/python2.7/os.py``
|
||||||
|
|
||||||
|
:rtype: str or None
|
||||||
|
"""
|
||||||
module = self._get_module_context()
|
module = self._get_module_context()
|
||||||
if module.is_stub() or not module.is_compiled():
|
if module.is_stub() or not module.is_compiled():
|
||||||
# Compiled modules should not return a module path even if they
|
# Compiled modules should not return a module path even if they
|
||||||
|
@ -168,7 +173,7 @@ class BaseName(object):
|
||||||
>>> defs[3]
|
>>> defs[3]
|
||||||
'function'
|
'function'
|
||||||
|
|
||||||
Valid values for are ``module``, ``class``, ``instance``, ``function``,
|
Valid values for type are ``module``, ``class``, ``instance``, ``function``,
|
||||||
``param``, ``path``, ``keyword`` and ``statement``.
|
``param``, ``path``, ``keyword`` and ``statement``.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -226,6 +231,39 @@ class BaseName(object):
|
||||||
return None
|
return None
|
||||||
return start_pos[1]
|
return start_pos[1]
|
||||||
|
|
||||||
|
def get_definition_start_position(self):
|
||||||
|
"""
|
||||||
|
The (row, column) of the start of the definition range. Rows start with
|
||||||
|
1, columns start with 0.
|
||||||
|
|
||||||
|
:rtype: Optional[Tuple[int, int]]
|
||||||
|
"""
|
||||||
|
if self._name.tree_name is None:
|
||||||
|
return None
|
||||||
|
definition = self._name.tree_name.get_definition()
|
||||||
|
if definition is None:
|
||||||
|
return self._name.start_pos
|
||||||
|
return definition.start_pos
|
||||||
|
|
||||||
|
def get_definition_end_position(self):
|
||||||
|
"""
|
||||||
|
The (row, column) of the end of the definition range. Rows start with
|
||||||
|
1, columns start with 0.
|
||||||
|
|
||||||
|
:rtype: Optional[Tuple[int, int]]
|
||||||
|
"""
|
||||||
|
if self._name.tree_name is None:
|
||||||
|
return None
|
||||||
|
definition = self._name.tree_name.get_definition()
|
||||||
|
if definition is None:
|
||||||
|
return self._name.tree_name.end_pos
|
||||||
|
if self.type in ("function", "class"):
|
||||||
|
last_leaf = definition.get_last_leaf()
|
||||||
|
if last_leaf.type == "newline":
|
||||||
|
return last_leaf.get_previous_leaf().end_pos
|
||||||
|
return last_leaf.end_pos
|
||||||
|
return definition.end_pos
|
||||||
|
|
||||||
def docstring(self, raw=False, fast=True):
|
def docstring(self, raw=False, fast=True):
|
||||||
r"""
|
r"""
|
||||||
Return a document string for this completion object.
|
Return a document string for this completion object.
|
||||||
|
@ -245,8 +283,8 @@ class BaseName(object):
|
||||||
Document for function f.
|
Document for function f.
|
||||||
|
|
||||||
Notice that useful extra information is added to the actual
|
Notice that useful extra information is added to the actual
|
||||||
docstring. For function, it is signature. If you need
|
docstring, e.g. function signatures are prepended to their docstrings.
|
||||||
actual docstring, use ``raw=True`` instead.
|
If you need the actual docstring, use ``raw=True`` instead.
|
||||||
|
|
||||||
>>> print(script.infer(1, len('def f'))[0].docstring(raw=True))
|
>>> print(script.infer(1, len('def f'))[0].docstring(raw=True))
|
||||||
Document for function f.
|
Document for function f.
|
||||||
|
@ -557,6 +595,12 @@ class BaseName(object):
|
||||||
# statements and not stubs. This is a speed optimization.
|
# statements and not stubs. This is a speed optimization.
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
if isinstance(self._name, MixedName):
|
||||||
|
# While this would eventually happen anyway, it's basically just a
|
||||||
|
# shortcut to not infer anything tree related, because it's really
|
||||||
|
# not necessary.
|
||||||
|
return self._name.infer_compiled_value().get_signatures()
|
||||||
|
|
||||||
names = convert_names([self._name], prefer_stubs=True)
|
names = convert_names([self._name], prefer_stubs=True)
|
||||||
return [sig for name in names for sig in name.infer().get_signatures()]
|
return [sig for name in names for sig in name.infer().get_signatures()]
|
||||||
|
|
||||||
|
@ -665,7 +709,7 @@ class Completion(BaseName):
|
||||||
|
|
||||||
def docstring(self, raw=False, fast=True):
|
def docstring(self, raw=False, fast=True):
|
||||||
"""
|
"""
|
||||||
Documentated under :meth:`BaseName.docstring`.
|
Documented under :meth:`BaseName.docstring`.
|
||||||
"""
|
"""
|
||||||
if self._like_name_length >= 3:
|
if self._like_name_length >= 3:
|
||||||
# In this case we can just resolve the like name, because we
|
# In this case we can just resolve the like name, because we
|
||||||
|
@ -693,9 +737,8 @@ class Completion(BaseName):
|
||||||
return super(Completion, self)._get_docstring_signature()
|
return super(Completion, self)._get_docstring_signature()
|
||||||
|
|
||||||
def _get_cache(self):
|
def _get_cache(self):
|
||||||
typ = super(Completion, self).type
|
|
||||||
return (
|
return (
|
||||||
typ,
|
super(Completion, self).type,
|
||||||
super(Completion, self)._get_docstring_signature(),
|
super(Completion, self)._get_docstring_signature(),
|
||||||
super(Completion, self)._get_docstring(),
|
super(Completion, self)._get_docstring(),
|
||||||
)
|
)
|
||||||
|
@ -703,7 +746,7 @@ class Completion(BaseName):
|
||||||
@property
|
@property
|
||||||
def type(self):
|
def type(self):
|
||||||
"""
|
"""
|
||||||
Documentated under :meth:`BaseName.type`.
|
Documented under :meth:`BaseName.type`.
|
||||||
"""
|
"""
|
||||||
# Purely a speed optimization.
|
# Purely a speed optimization.
|
||||||
if self._cached_name is not None:
|
if self._cached_name is not None:
|
||||||
|
@ -734,8 +777,7 @@ class Name(BaseName):
|
||||||
DeprecationWarning,
|
DeprecationWarning,
|
||||||
stacklevel=2
|
stacklevel=2
|
||||||
)
|
)
|
||||||
position = '' if self.in_builtin_module else '@%s' % self.line
|
return "%s:%s" % (self.module_name, self.description)
|
||||||
return "%s:%s%s" % (self.module_name, self.description, position)
|
|
||||||
|
|
||||||
@memoize_method
|
@memoize_method
|
||||||
def defined_names(self):
|
def defined_names(self):
|
||||||
|
@ -798,7 +840,7 @@ class BaseSignature(Name):
|
||||||
Returns a text representation of the signature. This could for example
|
Returns a text representation of the signature. This could for example
|
||||||
look like ``foo(bar, baz: int, **kwargs)``.
|
look like ``foo(bar, baz: int, **kwargs)``.
|
||||||
|
|
||||||
:return str
|
:rtype: str
|
||||||
"""
|
"""
|
||||||
return self._signature.to_string()
|
return self._signature.to_string()
|
||||||
|
|
||||||
|
@ -865,7 +907,7 @@ class ParamName(Name):
|
||||||
Returns a simple representation of a param, like
|
Returns a simple representation of a param, like
|
||||||
``f: Callable[..., Any]``.
|
``f: Callable[..., Any]``.
|
||||||
|
|
||||||
:rtype: :class:`str`
|
:rtype: str
|
||||||
"""
|
"""
|
||||||
return self._name.to_string()
|
return self._name.to_string()
|
||||||
|
|
||||||
|
|
|
@ -30,16 +30,43 @@ class ParamNameWithEquals(ParamNameWrapper):
|
||||||
return self.string_name + '='
|
return self.string_name + '='
|
||||||
|
|
||||||
|
|
||||||
def get_signature_param_names(signatures):
|
def _get_signature_param_names(signatures, positional_count, used_kwargs):
|
||||||
# add named params
|
# Add named params
|
||||||
for call_sig in signatures:
|
for call_sig in signatures:
|
||||||
for p in call_sig.params:
|
for i, p in enumerate(call_sig.params):
|
||||||
# Allow protected access, because it's a public API.
|
# Allow protected access, because it's a public API.
|
||||||
if p._name.get_kind() in (Parameter.POSITIONAL_OR_KEYWORD,
|
# TODO reconsider with Python 2 drop
|
||||||
Parameter.KEYWORD_ONLY):
|
kind = p._name.get_kind()
|
||||||
|
if i < positional_count and kind == Parameter.POSITIONAL_OR_KEYWORD:
|
||||||
|
continue
|
||||||
|
if kind in (Parameter.POSITIONAL_OR_KEYWORD, Parameter.KEYWORD_ONLY) \
|
||||||
|
and p.name not in used_kwargs:
|
||||||
yield ParamNameWithEquals(p._name)
|
yield ParamNameWithEquals(p._name)
|
||||||
|
|
||||||
|
|
||||||
|
def _must_be_kwarg(signatures, positional_count, used_kwargs):
|
||||||
|
if used_kwargs:
|
||||||
|
return True
|
||||||
|
|
||||||
|
must_be_kwarg = True
|
||||||
|
for signature in signatures:
|
||||||
|
for i, p in enumerate(signature.params):
|
||||||
|
# TODO reconsider with Python 2 drop
|
||||||
|
kind = p._name.get_kind()
|
||||||
|
if kind is Parameter.VAR_POSITIONAL:
|
||||||
|
# In case there were not already kwargs, the next param can
|
||||||
|
# always be a normal argument.
|
||||||
|
return False
|
||||||
|
|
||||||
|
if i >= positional_count and kind in (Parameter.POSITIONAL_OR_KEYWORD,
|
||||||
|
Parameter.POSITIONAL_ONLY):
|
||||||
|
must_be_kwarg = False
|
||||||
|
break
|
||||||
|
if not must_be_kwarg:
|
||||||
|
break
|
||||||
|
return must_be_kwarg
|
||||||
|
|
||||||
|
|
||||||
def filter_names(inference_state, completion_names, stack, like_name, fuzzy, cached_name):
|
def filter_names(inference_state, completion_names, stack, like_name, fuzzy, cached_name):
|
||||||
comp_dct = set()
|
comp_dct = set()
|
||||||
if settings.case_insensitive_completion:
|
if settings.case_insensitive_completion:
|
||||||
|
@ -229,14 +256,8 @@ class Completion:
|
||||||
allowed_transitions.append('else')
|
allowed_transitions.append('else')
|
||||||
|
|
||||||
completion_names = []
|
completion_names = []
|
||||||
current_line = self._code_lines[self._position[0] - 1][:self._position[1]]
|
|
||||||
|
|
||||||
completion_names += self._complete_keywords(
|
|
||||||
allowed_transitions,
|
|
||||||
only_values=not (not current_line or current_line[-1] in ' \t.;'
|
|
||||||
and current_line[-3:] != '...')
|
|
||||||
)
|
|
||||||
|
|
||||||
|
kwargs_only = False
|
||||||
if any(t in allowed_transitions for t in (PythonTokenTypes.NAME,
|
if any(t in allowed_transitions for t in (PythonTokenTypes.NAME,
|
||||||
PythonTokenTypes.INDENT)):
|
PythonTokenTypes.INDENT)):
|
||||||
# This means that we actually have to do type inference.
|
# This means that we actually have to do type inference.
|
||||||
|
@ -264,20 +285,41 @@ class Completion:
|
||||||
elif self._is_parameter_completion():
|
elif self._is_parameter_completion():
|
||||||
completion_names += self._complete_params(leaf)
|
completion_names += self._complete_params(leaf)
|
||||||
else:
|
else:
|
||||||
completion_names += self._complete_global_scope()
|
# Apparently this looks like it's good enough to filter most cases
|
||||||
completion_names += self._complete_inherited(is_function=False)
|
# so that signature completions don't randomly appear.
|
||||||
|
# To understand why this works, three things are important:
|
||||||
|
# 1. trailer with a `,` in it is either a subscript or an arglist.
|
||||||
|
# 2. If there's no `,`, it's at the start and only signatures start
|
||||||
|
# with `(`. Other trailers could start with `.` or `[`.
|
||||||
|
# 3. Decorators are very primitive and have an optional `(` with
|
||||||
|
# optional arglist in them.
|
||||||
|
if nodes[-1] in ['(', ','] \
|
||||||
|
and nonterminals[-1] in ('trailer', 'arglist', 'decorator'):
|
||||||
|
signatures = self._signatures_callback(*self._position)
|
||||||
|
if signatures:
|
||||||
|
call_details = signatures[0]._call_details
|
||||||
|
used_kwargs = list(call_details.iter_used_keyword_arguments())
|
||||||
|
positional_count = call_details.count_positional_arguments()
|
||||||
|
|
||||||
# Apparently this looks like it's good enough to filter most cases
|
completion_names += _get_signature_param_names(
|
||||||
# so that signature completions don't randomly appear.
|
signatures,
|
||||||
# To understand why this works, three things are important:
|
positional_count,
|
||||||
# 1. trailer with a `,` in it is either a subscript or an arglist.
|
used_kwargs,
|
||||||
# 2. If there's no `,`, it's at the start and only signatures start
|
)
|
||||||
# with `(`. Other trailers could start with `.` or `[`.
|
|
||||||
# 3. Decorators are very primitive and have an optional `(` with
|
kwargs_only = _must_be_kwarg(signatures, positional_count, used_kwargs)
|
||||||
# optional arglist in them.
|
|
||||||
if nodes[-1] in ['(', ','] and nonterminals[-1] in ('trailer', 'arglist', 'decorator'):
|
if not kwargs_only:
|
||||||
signatures = self._signatures_callback(*self._position)
|
completion_names += self._complete_global_scope()
|
||||||
completion_names += get_signature_param_names(signatures)
|
completion_names += self._complete_inherited(is_function=False)
|
||||||
|
|
||||||
|
if not kwargs_only:
|
||||||
|
current_line = self._code_lines[self._position[0] - 1][:self._position[1]]
|
||||||
|
completion_names += self._complete_keywords(
|
||||||
|
allowed_transitions,
|
||||||
|
only_values=not (not current_line or current_line[-1] in ' \t.;'
|
||||||
|
and current_line[-3:] != '...')
|
||||||
|
)
|
||||||
|
|
||||||
return cached_name, completion_names
|
return cached_name, completion_names
|
||||||
|
|
||||||
|
@ -301,19 +343,20 @@ class Completion:
|
||||||
if stack_node.nonterminal == 'funcdef':
|
if stack_node.nonterminal == 'funcdef':
|
||||||
context = get_user_context(self._module_context, self._position)
|
context = get_user_context(self._module_context, self._position)
|
||||||
node = search_ancestor(leaf, 'error_node', 'funcdef')
|
node = search_ancestor(leaf, 'error_node', 'funcdef')
|
||||||
if node.type == 'error_node':
|
if node is not None:
|
||||||
n = node.children[0]
|
if node.type == 'error_node':
|
||||||
if n.type == 'decorators':
|
n = node.children[0]
|
||||||
decorators = n.children
|
if n.type == 'decorators':
|
||||||
elif n.type == 'decorator':
|
decorators = n.children
|
||||||
decorators = [n]
|
elif n.type == 'decorator':
|
||||||
|
decorators = [n]
|
||||||
|
else:
|
||||||
|
decorators = []
|
||||||
else:
|
else:
|
||||||
decorators = []
|
decorators = node.get_decorators()
|
||||||
else:
|
function_name = stack_node.nodes[1]
|
||||||
decorators = node.get_decorators()
|
|
||||||
function_name = stack_node.nodes[1]
|
|
||||||
|
|
||||||
return complete_param_names(context, function_name.value, decorators)
|
return complete_param_names(context, function_name.value, decorators)
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def _complete_keywords(self, allowed_transitions, only_values):
|
def _complete_keywords(self, allowed_transitions, only_values):
|
||||||
|
@ -413,7 +456,7 @@ class Completion:
|
||||||
relevant_code_lines = list(iter_relevant_lines(code_lines))
|
relevant_code_lines = list(iter_relevant_lines(code_lines))
|
||||||
if relevant_code_lines[-1] is not None:
|
if relevant_code_lines[-1] is not None:
|
||||||
# Some code lines might be None, therefore get rid of that.
|
# Some code lines might be None, therefore get rid of that.
|
||||||
relevant_code_lines = [c or '\n' for c in relevant_code_lines]
|
relevant_code_lines = ['\n' if c is None else c for c in relevant_code_lines]
|
||||||
return self._complete_code_lines(relevant_code_lines)
|
return self._complete_code_lines(relevant_code_lines)
|
||||||
match = re.search(r'`([^`\s]+)', code_lines[-1])
|
match = re.search(r'`([^`\s]+)', code_lines[-1])
|
||||||
if match:
|
if match:
|
||||||
|
@ -544,6 +587,9 @@ def _complete_getattr(user_context, instance):
|
||||||
)
|
)
|
||||||
for func in functions:
|
for func in functions:
|
||||||
tree_node = func.tree_node
|
tree_node = func.tree_node
|
||||||
|
if tree_node is None or tree_node.type != 'funcdef':
|
||||||
|
continue
|
||||||
|
|
||||||
for return_stmt in tree_node.iter_return_stmts():
|
for return_stmt in tree_node.iter_return_stmts():
|
||||||
# Basically until the next comment we just try to find out if a
|
# Basically until the next comment we just try to find out if a
|
||||||
# return statement looks exactly like `return getattr(x, name)`.
|
# return statement looks exactly like `return getattr(x, name)`.
|
||||||
|
|
|
@ -35,6 +35,9 @@ class SyntaxError(object):
|
||||||
"""The column where the error ends (starting with 0)."""
|
"""The column where the error ends (starting with 0)."""
|
||||||
return self._parso_error.end_pos[1]
|
return self._parso_error.end_pos[1]
|
||||||
|
|
||||||
|
def get_message(self):
|
||||||
|
return self._parso_error.message
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<%s from=%s to=%s>' % (
|
return '<%s from=%s to=%s>' % (
|
||||||
self.__class__.__name__,
|
self.__class__.__name__,
|
||||||
|
|
|
@ -15,7 +15,7 @@ from jedi.inference.base_value import NO_VALUES
|
||||||
from jedi.inference.syntax_tree import infer_atom
|
from jedi.inference.syntax_tree import infer_atom
|
||||||
from jedi.inference.helpers import infer_call_of_leaf
|
from jedi.inference.helpers import infer_call_of_leaf
|
||||||
from jedi.inference.compiled import get_string_value_set
|
from jedi.inference.compiled import get_string_value_set
|
||||||
from jedi.cache import signature_time_cache
|
from jedi.cache import signature_time_cache, memoize_method
|
||||||
from jedi.parser_utils import get_parent_scope
|
from jedi.parser_utils import get_parent_scope
|
||||||
|
|
||||||
|
|
||||||
|
@ -216,11 +216,15 @@ class CallDetails(object):
|
||||||
def keyword_name_str(self):
|
def keyword_name_str(self):
|
||||||
return _get_index_and_key(self._children, self._position)[1]
|
return _get_index_and_key(self._children, self._position)[1]
|
||||||
|
|
||||||
|
@memoize_method
|
||||||
|
def _list_arguments(self):
|
||||||
|
return list(_iter_arguments(self._children, self._position))
|
||||||
|
|
||||||
def calculate_index(self, param_names):
|
def calculate_index(self, param_names):
|
||||||
positional_count = 0
|
positional_count = 0
|
||||||
used_names = set()
|
used_names = set()
|
||||||
star_count = -1
|
star_count = -1
|
||||||
args = list(_iter_arguments(self._children, self._position))
|
args = self._list_arguments()
|
||||||
if not args:
|
if not args:
|
||||||
if param_names:
|
if param_names:
|
||||||
return 0
|
return 0
|
||||||
|
@ -267,6 +271,19 @@ class CallDetails(object):
|
||||||
return i
|
return i
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def iter_used_keyword_arguments(self):
|
||||||
|
for star_count, key_start, had_equal in list(self._list_arguments()):
|
||||||
|
if had_equal and key_start:
|
||||||
|
yield key_start
|
||||||
|
|
||||||
|
def count_positional_arguments(self):
|
||||||
|
count = 0
|
||||||
|
for star_count, key_start, had_equal in self._list_arguments()[:-1]:
|
||||||
|
if star_count:
|
||||||
|
break
|
||||||
|
count += 1
|
||||||
|
return count
|
||||||
|
|
||||||
|
|
||||||
def _iter_arguments(nodes, position):
|
def _iter_arguments(nodes, position):
|
||||||
def remove_after_pos(name):
|
def remove_after_pos(name):
|
||||||
|
@ -385,7 +402,7 @@ def get_signature_details(module, position):
|
||||||
# parents for possible function definitions.
|
# parents for possible function definitions.
|
||||||
node = leaf.parent
|
node = leaf.parent
|
||||||
while node is not None:
|
while node is not None:
|
||||||
if node.type in ('funcdef', 'classdef'):
|
if node.type in ('funcdef', 'classdef', 'decorated', 'async_stmt'):
|
||||||
# Don't show signatures if there's stuff before it that just
|
# Don't show signatures if there's stuff before it that just
|
||||||
# makes it feel strange to have a signature.
|
# makes it feel strange to have a signature.
|
||||||
return None
|
return None
|
||||||
|
@ -405,7 +422,8 @@ def get_signature_details(module, position):
|
||||||
additional_children.insert(0, n)
|
additional_children.insert(0, n)
|
||||||
|
|
||||||
# Find a valid trailer
|
# Find a valid trailer
|
||||||
if node.type == 'trailer' and node.children[0] == '(':
|
if node.type == 'trailer' and node.children[0] == '(' \
|
||||||
|
or node.type == 'decorator' and node.children[2] == '(':
|
||||||
# Additionally we have to check that an ending parenthesis isn't
|
# Additionally we have to check that an ending parenthesis isn't
|
||||||
# interpreted wrong. There are two cases:
|
# interpreted wrong. There are two cases:
|
||||||
# 1. Cursor before paren -> The current signature is good
|
# 1. Cursor before paren -> The current signature is good
|
||||||
|
@ -414,7 +432,11 @@ def get_signature_details(module, position):
|
||||||
leaf = node.get_previous_leaf()
|
leaf = node.get_previous_leaf()
|
||||||
if leaf is None:
|
if leaf is None:
|
||||||
return None
|
return None
|
||||||
return CallDetails(node.children[0], node.children, position)
|
return CallDetails(
|
||||||
|
node.children[0] if node.type == 'trailer' else node.children[2],
|
||||||
|
node.children,
|
||||||
|
position
|
||||||
|
)
|
||||||
|
|
||||||
node = node.parent
|
node = node.parent
|
||||||
|
|
||||||
|
@ -453,8 +475,8 @@ def validate_line_column(func):
|
||||||
line_string = self._code_lines[line - 1]
|
line_string = self._code_lines[line - 1]
|
||||||
line_len = len(line_string)
|
line_len = len(line_string)
|
||||||
if line_string.endswith('\r\n'):
|
if line_string.endswith('\r\n'):
|
||||||
line_len -= 1
|
line_len -= 2
|
||||||
if line_string.endswith('\n'):
|
elif line_string.endswith('\n'):
|
||||||
line_len -= 1
|
line_len -= 1
|
||||||
|
|
||||||
column = line_len if column is None else column
|
column = line_len if column is None else column
|
||||||
|
|
|
@ -13,7 +13,7 @@ import json
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from jedi._compatibility import FileNotFoundError, PermissionError, \
|
from jedi._compatibility import FileNotFoundError, PermissionError, \
|
||||||
IsADirectoryError
|
IsADirectoryError, NotADirectoryError
|
||||||
from jedi import debug
|
from jedi import debug
|
||||||
from jedi.api.environment import get_cached_default_environment, create_environment
|
from jedi.api.environment import get_cached_default_environment, create_environment
|
||||||
from jedi.api.exceptions import WrongVersion
|
from jedi.api.exceptions import WrongVersion
|
||||||
|
@ -26,7 +26,7 @@ from jedi.inference.sys_path import discover_buildout_paths
|
||||||
from jedi.inference.cache import inference_state_as_method_param_cache
|
from jedi.inference.cache import inference_state_as_method_param_cache
|
||||||
from jedi.inference.references import recurse_find_python_folders_and_files, search_in_file_ios
|
from jedi.inference.references import recurse_find_python_folders_and_files, search_in_file_ios
|
||||||
from jedi.file_io import FolderIO
|
from jedi.file_io import FolderIO
|
||||||
from jedi.common.utils import traverse_parents
|
from jedi.common import traverse_parents
|
||||||
|
|
||||||
_CONFIG_FOLDER = '.jedi'
|
_CONFIG_FOLDER = '.jedi'
|
||||||
_CONTAINS_POTENTIAL_PROJECT = \
|
_CONTAINS_POTENTIAL_PROJECT = \
|
||||||
|
@ -383,6 +383,8 @@ def get_default_project(path=None):
|
||||||
return Project.load(dir)
|
return Project.load(dir)
|
||||||
except (FileNotFoundError, IsADirectoryError, PermissionError):
|
except (FileNotFoundError, IsADirectoryError, PermissionError):
|
||||||
pass
|
pass
|
||||||
|
except NotADirectoryError:
|
||||||
|
continue
|
||||||
|
|
||||||
if first_no_init_file is None:
|
if first_no_init_file is None:
|
||||||
if os.path.exists(os.path.join(dir, '__init__.py')):
|
if os.path.exists(os.path.join(dir, '__init__.py')):
|
||||||
|
|
|
@ -25,11 +25,33 @@ class ChangedFile(object):
|
||||||
def get_diff(self):
|
def get_diff(self):
|
||||||
old_lines = split_lines(self._module_node.get_code(), keepends=True)
|
old_lines = split_lines(self._module_node.get_code(), keepends=True)
|
||||||
new_lines = split_lines(self.get_new_code(), keepends=True)
|
new_lines = split_lines(self.get_new_code(), keepends=True)
|
||||||
|
|
||||||
|
# Add a newline at the end if it's missing. Otherwise the diff will be
|
||||||
|
# very weird. A `diff -u file1 file2` would show the string:
|
||||||
|
#
|
||||||
|
# \ No newline at end of file
|
||||||
|
#
|
||||||
|
# This is not necessary IMO, because Jedi does not really play with
|
||||||
|
# newlines and the ending newline does not really matter in Python
|
||||||
|
# files. ~dave
|
||||||
|
if old_lines[-1] != '':
|
||||||
|
old_lines[-1] += '\n'
|
||||||
|
if new_lines[-1] != '':
|
||||||
|
new_lines[-1] += '\n'
|
||||||
|
|
||||||
project_path = self._inference_state.project._path
|
project_path = self._inference_state.project._path
|
||||||
|
if self._from_path is None:
|
||||||
|
from_p = ''
|
||||||
|
else:
|
||||||
|
from_p = relpath(self._from_path, project_path)
|
||||||
|
if self._to_path is None:
|
||||||
|
to_p = ''
|
||||||
|
else:
|
||||||
|
to_p = relpath(self._to_path, project_path)
|
||||||
diff = difflib.unified_diff(
|
diff = difflib.unified_diff(
|
||||||
old_lines, new_lines,
|
old_lines, new_lines,
|
||||||
fromfile=relpath(self._from_path, project_path),
|
fromfile=from_p,
|
||||||
tofile=relpath(self._to_path, project_path),
|
tofile=to_p,
|
||||||
)
|
)
|
||||||
# Apparently there's a space at the end of the diff - for whatever
|
# Apparently there's a space at the end of the diff - for whatever
|
||||||
# reason.
|
# reason.
|
||||||
|
@ -151,6 +173,8 @@ def inline(inference_state, names):
|
||||||
raise RefactoringError("No definition found to inline")
|
raise RefactoringError("No definition found to inline")
|
||||||
if len(definitions) > 1:
|
if len(definitions) > 1:
|
||||||
raise RefactoringError("Cannot inline a name with multiple definitions")
|
raise RefactoringError("Cannot inline a name with multiple definitions")
|
||||||
|
if len(names) == 1:
|
||||||
|
raise RefactoringError("There are no references to this name")
|
||||||
|
|
||||||
tree_name = definitions[0].tree_name
|
tree_name = definitions[0].tree_name
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,10 @@ from parso import split_lines
|
||||||
from jedi import debug
|
from jedi import debug
|
||||||
from jedi.api.exceptions import RefactoringError
|
from jedi.api.exceptions import RefactoringError
|
||||||
from jedi.api.refactoring import Refactoring, EXPRESSION_PARTS
|
from jedi.api.refactoring import Refactoring, EXPRESSION_PARTS
|
||||||
from jedi.common.utils import indent_block
|
from jedi.common import indent_block
|
||||||
from jedi.parser_utils import function_is_classmethod, function_is_staticmethod
|
from jedi.parser_utils import function_is_classmethod, function_is_staticmethod
|
||||||
|
|
||||||
|
|
||||||
_EXTRACT_USE_PARENT = EXPRESSION_PARTS + ['trailer']
|
|
||||||
_DEFINITION_SCOPES = ('suite', 'file_input')
|
_DEFINITION_SCOPES = ('suite', 'file_input')
|
||||||
_VARIABLE_EXCTRACTABLE = EXPRESSION_PARTS + \
|
_VARIABLE_EXCTRACTABLE = EXPRESSION_PARTS + \
|
||||||
('atom testlist_star_expr testlist test lambdef lambdef_nocond '
|
('atom testlist_star_expr testlist test lambdef lambdef_nocond '
|
||||||
|
@ -57,7 +56,9 @@ def _find_nodes(module_node, pos, until_pos):
|
||||||
if _is_not_extractable_syntax(start_node):
|
if _is_not_extractable_syntax(start_node):
|
||||||
start_node = start_node.parent
|
start_node = start_node.parent
|
||||||
|
|
||||||
while start_node.parent.type in _EXTRACT_USE_PARENT:
|
if start_node.parent.type == 'trailer':
|
||||||
|
start_node = start_node.parent.parent
|
||||||
|
while start_node.parent.type in EXPRESSION_PARTS:
|
||||||
start_node = start_node.parent
|
start_node = start_node.parent
|
||||||
|
|
||||||
nodes = [start_node]
|
nodes = [start_node]
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
from jedi.common.value import BaseValueSet, BaseValue
|
|
|
@ -1,36 +0,0 @@
|
||||||
import os
|
|
||||||
from contextlib import contextmanager
|
|
||||||
|
|
||||||
|
|
||||||
def traverse_parents(path, include_current=False):
|
|
||||||
if not include_current:
|
|
||||||
path = os.path.dirname(path)
|
|
||||||
|
|
||||||
previous = None
|
|
||||||
while previous != path:
|
|
||||||
yield path
|
|
||||||
previous = path
|
|
||||||
path = os.path.dirname(path)
|
|
||||||
|
|
||||||
|
|
||||||
@contextmanager
|
|
||||||
def monkeypatch(obj, attribute_name, new_value):
|
|
||||||
"""
|
|
||||||
Like pytest's monkeypatch, but as a value manager.
|
|
||||||
"""
|
|
||||||
old_value = getattr(obj, attribute_name)
|
|
||||||
try:
|
|
||||||
setattr(obj, attribute_name, new_value)
|
|
||||||
yield
|
|
||||||
finally:
|
|
||||||
setattr(obj, attribute_name, old_value)
|
|
||||||
|
|
||||||
|
|
||||||
def indent_block(text, indention=' '):
|
|
||||||
"""This function indents a text block with a default of four spaces."""
|
|
||||||
temp = ''
|
|
||||||
while text and text[-1] == '\n':
|
|
||||||
temp += text[-1]
|
|
||||||
text = text[:-1]
|
|
||||||
lines = text.split('\n')
|
|
||||||
return '\n'.join(map(lambda s: indention + s, lines)) + temp
|
|
|
@ -1,113 +0,0 @@
|
||||||
class BaseValue(object):
|
|
||||||
def __init__(self, inference_state, parent_context=None):
|
|
||||||
self.inference_state = inference_state
|
|
||||||
self.parent_context = parent_context
|
|
||||||
|
|
||||||
def get_root_context(self):
|
|
||||||
value = self
|
|
||||||
while True:
|
|
||||||
if value.parent_context is None:
|
|
||||||
return value
|
|
||||||
value = value.parent_context
|
|
||||||
|
|
||||||
def infer_type_vars(self, value_set, is_class_value=False):
|
|
||||||
"""
|
|
||||||
When the current instance represents a type annotation, this method
|
|
||||||
tries to find information about undefined type vars and returns a dict
|
|
||||||
from type var name to value set.
|
|
||||||
|
|
||||||
This is for example important to understand what `iter([1])` returns.
|
|
||||||
According to typeshed, `iter` returns an `Iterator[_T]`:
|
|
||||||
|
|
||||||
def iter(iterable: Iterable[_T]) -> Iterator[_T]: ...
|
|
||||||
|
|
||||||
This functions would generate `int` for `_T` in this case, because it
|
|
||||||
unpacks the `Iterable`.
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
|
|
||||||
`self`: represents the annotation of the current parameter to infer the
|
|
||||||
value for. In the above example, this would initially be the
|
|
||||||
`Iterable[_T]` of the `iterable` parameter and then, when recursing,
|
|
||||||
just the `_T` generic parameter.
|
|
||||||
|
|
||||||
`value_set`: represents the actual argument passed to the parameter
|
|
||||||
we're inferrined for, or (for recursive calls) their types. In the
|
|
||||||
above example this would first be the representation of the list
|
|
||||||
`[1]` and then, when recursing, just of `1`.
|
|
||||||
|
|
||||||
`is_class_value`: tells us whether or not to treat the `value_set` as
|
|
||||||
representing the instances or types being passed, which is neccesary
|
|
||||||
to correctly cope with `Type[T]` annotations. When it is True, this
|
|
||||||
means that we are being called with a nested portion of an
|
|
||||||
annotation and that the `value_set` represents the types of the
|
|
||||||
arguments, rather than their actual instances. Note: not all
|
|
||||||
recursive calls will neccesarily set this to True.
|
|
||||||
"""
|
|
||||||
return {}
|
|
||||||
|
|
||||||
|
|
||||||
class BaseValueSet(object):
|
|
||||||
def __init__(self, iterable):
|
|
||||||
self._set = frozenset(iterable)
|
|
||||||
for value in iterable:
|
|
||||||
assert not isinstance(value, BaseValueSet)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def _from_frozen_set(cls, frozenset_):
|
|
||||||
self = cls.__new__(cls)
|
|
||||||
self._set = frozenset_
|
|
||||||
return self
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_sets(cls, sets):
|
|
||||||
"""
|
|
||||||
Used to work with an iterable of set.
|
|
||||||
"""
|
|
||||||
aggregated = set()
|
|
||||||
for set_ in sets:
|
|
||||||
if isinstance(set_, BaseValueSet):
|
|
||||||
aggregated |= set_._set
|
|
||||||
else:
|
|
||||||
aggregated |= frozenset(set_)
|
|
||||||
return cls._from_frozen_set(frozenset(aggregated))
|
|
||||||
|
|
||||||
def __or__(self, other):
|
|
||||||
return self._from_frozen_set(self._set | other._set)
|
|
||||||
|
|
||||||
def __and__(self, other):
|
|
||||||
return self._from_frozen_set(self._set & other._set)
|
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
for element in self._set:
|
|
||||||
yield element
|
|
||||||
|
|
||||||
def __bool__(self):
|
|
||||||
return bool(self._set)
|
|
||||||
|
|
||||||
def __len__(self):
|
|
||||||
return len(self._set)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return 'S{%s}' % (', '.join(str(s) for s in self._set))
|
|
||||||
|
|
||||||
def filter(self, filter_func):
|
|
||||||
return self.__class__(filter(filter_func, self._set))
|
|
||||||
|
|
||||||
def __getattr__(self, name):
|
|
||||||
def mapper(*args, **kwargs):
|
|
||||||
return self.from_sets(
|
|
||||||
getattr(value, name)(*args, **kwargs)
|
|
||||||
for value in self._set
|
|
||||||
)
|
|
||||||
return mapper
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
|
||||||
return self._set == other._set
|
|
||||||
|
|
||||||
def __ne__(self, other):
|
|
||||||
return not self.__eq__(other)
|
|
||||||
|
|
||||||
def __hash__(self):
|
|
||||||
return hash(self._set)
|
|
|
@ -84,17 +84,17 @@ def increase_indent(func):
|
||||||
|
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def increase_indent_cm(title=None):
|
def increase_indent_cm(title=None, color='MAGENTA'):
|
||||||
global _debug_indent
|
global _debug_indent
|
||||||
if title:
|
if title:
|
||||||
dbg('Start: ' + title, color='MAGENTA')
|
dbg('Start: ' + title, color=color)
|
||||||
_debug_indent += 1
|
_debug_indent += 1
|
||||||
try:
|
try:
|
||||||
yield
|
yield
|
||||||
finally:
|
finally:
|
||||||
_debug_indent -= 1
|
_debug_indent -= 1
|
||||||
if title:
|
if title:
|
||||||
dbg('End: ' + title, color='MAGENTA')
|
dbg('End: ' + title, color=color)
|
||||||
|
|
||||||
|
|
||||||
def dbg(message, *args, **kwargs):
|
def dbg(message, *args, **kwargs):
|
||||||
|
|
|
@ -35,7 +35,7 @@ class ParamIssue(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def repack_with_argument_clinic(string, keep_arguments_param=False, keep_callback_param=False):
|
def repack_with_argument_clinic(clinic_string):
|
||||||
"""
|
"""
|
||||||
Transforms a function or method with arguments to the signature that is
|
Transforms a function or method with arguments to the signature that is
|
||||||
given as an argument clinic notation.
|
given as an argument clinic notation.
|
||||||
|
@ -46,35 +46,29 @@ def repack_with_argument_clinic(string, keep_arguments_param=False, keep_callbac
|
||||||
str.split.__text_signature__
|
str.split.__text_signature__
|
||||||
# Results in: '($self, /, sep=None, maxsplit=-1)'
|
# Results in: '($self, /, sep=None, maxsplit=-1)'
|
||||||
"""
|
"""
|
||||||
clinic_args = list(_parse_argument_clinic(string))
|
|
||||||
|
|
||||||
def decorator(func):
|
def decorator(func):
|
||||||
def wrapper(context, *args, **kwargs):
|
def wrapper(value, arguments):
|
||||||
if keep_arguments_param:
|
|
||||||
arguments = kwargs['arguments']
|
|
||||||
else:
|
|
||||||
arguments = kwargs.pop('arguments')
|
|
||||||
if not keep_arguments_param:
|
|
||||||
kwargs.pop('callback', None)
|
|
||||||
try:
|
try:
|
||||||
args += tuple(_iterate_argument_clinic(
|
args = tuple(iterate_argument_clinic(
|
||||||
context.inference_state,
|
value.inference_state,
|
||||||
arguments,
|
arguments,
|
||||||
clinic_args
|
clinic_string,
|
||||||
))
|
))
|
||||||
except ParamIssue:
|
except ParamIssue:
|
||||||
return NO_VALUES
|
return NO_VALUES
|
||||||
else:
|
else:
|
||||||
return func(context, *args, **kwargs)
|
return func(value, *args)
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
def _iterate_argument_clinic(inference_state, arguments, parameters):
|
def iterate_argument_clinic(inference_state, arguments, clinic_string):
|
||||||
"""Uses a list with argument clinic information (see PEP 436)."""
|
"""Uses a list with argument clinic information (see PEP 436)."""
|
||||||
|
clinic_args = list(_parse_argument_clinic(clinic_string))
|
||||||
|
|
||||||
iterator = PushBackIterator(arguments.unpack())
|
iterator = PushBackIterator(arguments.unpack())
|
||||||
for i, (name, optional, allow_kwargs, stars) in enumerate(parameters):
|
for i, (name, optional, allow_kwargs, stars) in enumerate(clinic_args):
|
||||||
if stars == 1:
|
if stars == 1:
|
||||||
lazy_values = []
|
lazy_values = []
|
||||||
for key, argument in iterator:
|
for key, argument in iterator:
|
||||||
|
@ -94,7 +88,7 @@ def _iterate_argument_clinic(inference_state, arguments, parameters):
|
||||||
raise ParamIssue
|
raise ParamIssue
|
||||||
if argument is None and not optional:
|
if argument is None and not optional:
|
||||||
debug.warning('TypeError: %s expected at least %s arguments, got %s',
|
debug.warning('TypeError: %s expected at least %s arguments, got %s',
|
||||||
name, len(parameters), i)
|
name, len(clinic_args), i)
|
||||||
raise ParamIssue
|
raise ParamIssue
|
||||||
|
|
||||||
value_set = NO_VALUES if argument is None else argument.infer()
|
value_set = NO_VALUES if argument is None else argument.infer()
|
||||||
|
|
|
@ -13,7 +13,6 @@ from parso.python.tree import Name
|
||||||
from jedi import debug
|
from jedi import debug
|
||||||
from jedi._compatibility import zip_longest, unicode
|
from jedi._compatibility import zip_longest, unicode
|
||||||
from jedi.parser_utils import clean_scope_docstring
|
from jedi.parser_utils import clean_scope_docstring
|
||||||
from jedi.common import BaseValueSet, BaseValue
|
|
||||||
from jedi.inference.helpers import SimpleGetItemNotFound
|
from jedi.inference.helpers import SimpleGetItemNotFound
|
||||||
from jedi.inference.utils import safe_property
|
from jedi.inference.utils import safe_property
|
||||||
from jedi.inference.cache import inference_state_as_method_param_cache
|
from jedi.inference.cache import inference_state_as_method_param_cache
|
||||||
|
@ -33,11 +32,6 @@ class HelperValueMixin(object):
|
||||||
return value
|
return value
|
||||||
value = value.parent_context
|
value = value.parent_context
|
||||||
|
|
||||||
@classmethod
|
|
||||||
@inference_state_as_method_param_cache()
|
|
||||||
def create_cached(cls, *args, **kwargs):
|
|
||||||
return cls(*args, **kwargs)
|
|
||||||
|
|
||||||
def execute(self, arguments):
|
def execute(self, arguments):
|
||||||
return self.inference_state.execute(self, arguments=arguments)
|
return self.inference_state.execute(self, arguments=arguments)
|
||||||
|
|
||||||
|
@ -120,10 +114,14 @@ class HelperValueMixin(object):
|
||||||
return self.py__iter__(contextualized_node)
|
return self.py__iter__(contextualized_node)
|
||||||
|
|
||||||
def is_sub_class_of(self, class_value):
|
def is_sub_class_of(self, class_value):
|
||||||
for cls in self.py__mro__():
|
with debug.increase_indent_cm('subclass matching of %s <=> %s' % (self, class_value),
|
||||||
if cls.is_same_class(class_value):
|
color='BLUE'):
|
||||||
return True
|
for cls in self.py__mro__():
|
||||||
return False
|
if cls.is_same_class(class_value):
|
||||||
|
debug.dbg('matched subclass True', color='BLUE')
|
||||||
|
return True
|
||||||
|
debug.dbg('matched subclass False', color='BLUE')
|
||||||
|
return False
|
||||||
|
|
||||||
def is_same_class(self, class2):
|
def is_same_class(self, class2):
|
||||||
# Class matching should prefer comparisons that are not this function.
|
# Class matching should prefer comparisons that are not this function.
|
||||||
|
@ -136,7 +134,7 @@ class HelperValueMixin(object):
|
||||||
return self._as_context(*args, **kwargs)
|
return self._as_context(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class Value(HelperValueMixin, BaseValue):
|
class Value(HelperValueMixin):
|
||||||
"""
|
"""
|
||||||
To be implemented by subclasses.
|
To be implemented by subclasses.
|
||||||
"""
|
"""
|
||||||
|
@ -144,12 +142,11 @@ class Value(HelperValueMixin, BaseValue):
|
||||||
# Possible values: None, tuple, list, dict and set. Here to deal with these
|
# Possible values: None, tuple, list, dict and set. Here to deal with these
|
||||||
# very important containers.
|
# very important containers.
|
||||||
array_type = None
|
array_type = None
|
||||||
|
api_type = 'not_defined_please_report_bug'
|
||||||
|
|
||||||
@property
|
def __init__(self, inference_state, parent_context=None):
|
||||||
def api_type(self):
|
self.inference_state = inference_state
|
||||||
# By default just lower name of the class. Can and should be
|
self.parent_context = parent_context
|
||||||
# overwritten.
|
|
||||||
return self.__class__.__name__.lower()
|
|
||||||
|
|
||||||
def py__getitem__(self, index_value_set, contextualized_node):
|
def py__getitem__(self, index_value_set, contextualized_node):
|
||||||
from jedi.inference import analysis
|
from jedi.inference import analysis
|
||||||
|
@ -181,6 +178,9 @@ class Value(HelperValueMixin, BaseValue):
|
||||||
def is_class(self):
|
def is_class(self):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def is_class_mixin(self):
|
||||||
|
return False
|
||||||
|
|
||||||
def is_instance(self):
|
def is_instance(self):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -244,6 +244,9 @@ class Value(HelperValueMixin, BaseValue):
|
||||||
debug.warning("No __get__ defined on %s", self)
|
debug.warning("No __get__ defined on %s", self)
|
||||||
return ValueSet([self])
|
return ValueSet([self])
|
||||||
|
|
||||||
|
def py__get__on_class(self, calling_instance, instance, class_value):
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
def get_qualified_names(self):
|
def get_qualified_names(self):
|
||||||
# Returns Optional[Tuple[str, ...]]
|
# Returns Optional[Tuple[str, ...]]
|
||||||
return None
|
return None
|
||||||
|
@ -265,6 +268,35 @@ class Value(HelperValueMixin, BaseValue):
|
||||||
def get_type_hint(self, add_class_info=True):
|
def get_type_hint(self, add_class_info=True):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def infer_type_vars(self, value_set):
|
||||||
|
"""
|
||||||
|
When the current instance represents a type annotation, this method
|
||||||
|
tries to find information about undefined type vars and returns a dict
|
||||||
|
from type var name to value set.
|
||||||
|
|
||||||
|
This is for example important to understand what `iter([1])` returns.
|
||||||
|
According to typeshed, `iter` returns an `Iterator[_T]`:
|
||||||
|
|
||||||
|
def iter(iterable: Iterable[_T]) -> Iterator[_T]: ...
|
||||||
|
|
||||||
|
This functions would generate `int` for `_T` in this case, because it
|
||||||
|
unpacks the `Iterable`.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
|
||||||
|
`self`: represents the annotation of the current parameter to infer the
|
||||||
|
value for. In the above example, this would initially be the
|
||||||
|
`Iterable[_T]` of the `iterable` parameter and then, when recursing,
|
||||||
|
just the `_T` generic parameter.
|
||||||
|
|
||||||
|
`value_set`: represents the actual argument passed to the parameter
|
||||||
|
we're inferrined for, or (for recursive calls) their types. In the
|
||||||
|
above example this would first be the representation of the list
|
||||||
|
`[1]` and then, when recursing, just of `1`.
|
||||||
|
"""
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
def iterate_values(values, contextualized_node=None, is_async=False):
|
def iterate_values(values, contextualized_node=None, is_async=False):
|
||||||
"""
|
"""
|
||||||
|
@ -371,7 +403,70 @@ def _getitem(value, index_values, contextualized_node):
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
class ValueSet(BaseValueSet):
|
class ValueSet(object):
|
||||||
|
def __init__(self, iterable):
|
||||||
|
self._set = frozenset(iterable)
|
||||||
|
for value in iterable:
|
||||||
|
assert not isinstance(value, ValueSet)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _from_frozen_set(cls, frozenset_):
|
||||||
|
self = cls.__new__(cls)
|
||||||
|
self._set = frozenset_
|
||||||
|
return self
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_sets(cls, sets):
|
||||||
|
"""
|
||||||
|
Used to work with an iterable of set.
|
||||||
|
"""
|
||||||
|
aggregated = set()
|
||||||
|
for set_ in sets:
|
||||||
|
if isinstance(set_, ValueSet):
|
||||||
|
aggregated |= set_._set
|
||||||
|
else:
|
||||||
|
aggregated |= frozenset(set_)
|
||||||
|
return cls._from_frozen_set(frozenset(aggregated))
|
||||||
|
|
||||||
|
def __or__(self, other):
|
||||||
|
return self._from_frozen_set(self._set | other._set)
|
||||||
|
|
||||||
|
def __and__(self, other):
|
||||||
|
return self._from_frozen_set(self._set & other._set)
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
for element in self._set:
|
||||||
|
yield element
|
||||||
|
|
||||||
|
def __bool__(self):
|
||||||
|
return bool(self._set)
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self._set)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return 'S{%s}' % (', '.join(str(s) for s in self._set))
|
||||||
|
|
||||||
|
def filter(self, filter_func):
|
||||||
|
return self.__class__(filter(filter_func, self._set))
|
||||||
|
|
||||||
|
def __getattr__(self, name):
|
||||||
|
def mapper(*args, **kwargs):
|
||||||
|
return self.from_sets(
|
||||||
|
getattr(value, name)(*args, **kwargs)
|
||||||
|
for value in self._set
|
||||||
|
)
|
||||||
|
return mapper
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return self._set == other._set
|
||||||
|
|
||||||
|
def __ne__(self, other):
|
||||||
|
return not self.__eq__(other)
|
||||||
|
|
||||||
|
def __hash__(self):
|
||||||
|
return hash(self._set)
|
||||||
|
|
||||||
def py__class__(self):
|
def py__class__(self):
|
||||||
return ValueSet(c.py__class__() for c in self._set)
|
return ValueSet(c.py__class__() for c in self._set)
|
||||||
|
|
||||||
|
@ -435,7 +530,7 @@ class ValueSet(BaseValueSet):
|
||||||
s = 'Optional[%s]' % s
|
s = 'Optional[%s]' % s
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def infer_type_vars(self, value_set, is_class_value=False):
|
def infer_type_vars(self, value_set):
|
||||||
# Circular
|
# Circular
|
||||||
from jedi.inference.gradual.annotation import merge_type_var_dicts
|
from jedi.inference.gradual.annotation import merge_type_var_dicts
|
||||||
|
|
||||||
|
@ -443,7 +538,7 @@ class ValueSet(BaseValueSet):
|
||||||
for value in self._set:
|
for value in self._set:
|
||||||
merge_type_var_dicts(
|
merge_type_var_dicts(
|
||||||
type_var_dict,
|
type_var_dict,
|
||||||
value.infer_type_vars(value_set, is_class_value),
|
value.infer_type_vars(value_set),
|
||||||
)
|
)
|
||||||
return type_var_dict
|
return type_var_dict
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
default otherwise.
|
default otherwise.
|
||||||
- ``CachedMetaClass`` uses ``_memoize_default`` to do the same with classes.
|
- ``CachedMetaClass`` uses ``_memoize_default`` to do the same with classes.
|
||||||
"""
|
"""
|
||||||
|
from functools import wraps
|
||||||
|
|
||||||
from jedi import debug
|
from jedi import debug
|
||||||
|
|
||||||
|
@ -86,6 +87,7 @@ def inference_state_method_generator_cache():
|
||||||
recursion errors and returns no further iterator elemends in that case.
|
recursion errors and returns no further iterator elemends in that case.
|
||||||
"""
|
"""
|
||||||
def func(function):
|
def func(function):
|
||||||
|
@wraps(function)
|
||||||
def wrapper(obj, *args, **kwargs):
|
def wrapper(obj, *args, **kwargs):
|
||||||
cache = obj.inference_state.memoize_cache
|
cache = obj.inference_state.memoize_cache
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -485,9 +485,9 @@ class DirectObjectAccess(object):
|
||||||
return inspect.isclass(self._obj) and self._obj != type
|
return inspect.isclass(self._obj) and self._obj != type
|
||||||
|
|
||||||
def _annotation_to_str(self, annotation):
|
def _annotation_to_str(self, annotation):
|
||||||
if isinstance(annotation, type):
|
if py_version < 30:
|
||||||
return str(annotation.__name__)
|
return ''
|
||||||
return str(annotation)
|
return inspect.formatannotation(annotation)
|
||||||
|
|
||||||
def get_signature_params(self):
|
def get_signature_params(self):
|
||||||
return [
|
return [
|
||||||
|
|
|
@ -181,6 +181,15 @@ class CompiledSubprocess(object):
|
||||||
os.path.dirname(os.path.dirname(parso_path)),
|
os.path.dirname(os.path.dirname(parso_path)),
|
||||||
'.'.join(str(x) for x in sys.version_info[:3]),
|
'.'.join(str(x) for x in sys.version_info[:3]),
|
||||||
)
|
)
|
||||||
|
# Use explicit envionment to ensure reliable results (#1540)
|
||||||
|
env = {}
|
||||||
|
if os.name == 'nt':
|
||||||
|
# if SYSTEMROOT (or case variant) exists in environment,
|
||||||
|
# ensure it goes to subprocess
|
||||||
|
for k, v in os.environ.items():
|
||||||
|
if 'SYSTEMROOT' == k.upper():
|
||||||
|
env.update({k: os.environ[k]})
|
||||||
|
break # don't risk multiple entries
|
||||||
process = GeneralizedPopen(
|
process = GeneralizedPopen(
|
||||||
args,
|
args,
|
||||||
stdin=subprocess.PIPE,
|
stdin=subprocess.PIPE,
|
||||||
|
@ -188,7 +197,8 @@ class CompiledSubprocess(object):
|
||||||
stderr=subprocess.PIPE,
|
stderr=subprocess.PIPE,
|
||||||
# Use system default buffering on Python 2 to improve performance
|
# Use system default buffering on Python 2 to improve performance
|
||||||
# (this is already the case on Python 3).
|
# (this is already the case on Python 3).
|
||||||
bufsize=-1
|
bufsize=-1,
|
||||||
|
env=env
|
||||||
)
|
)
|
||||||
self._stderr_queue = Queue()
|
self._stderr_queue = Queue()
|
||||||
self._stderr_thread = t = Thread(
|
self._stderr_thread = t = Thread(
|
||||||
|
|
|
@ -23,7 +23,7 @@ from parso import parse, ParserSyntaxError
|
||||||
|
|
||||||
from jedi._compatibility import u
|
from jedi._compatibility import u
|
||||||
from jedi import debug
|
from jedi import debug
|
||||||
from jedi.common.utils import indent_block
|
from jedi.common import indent_block
|
||||||
from jedi.inference.cache import inference_state_method_cache
|
from jedi.inference.cache import inference_state_method_cache
|
||||||
from jedi.inference.base_value import iterator_to_value_set, ValueSet, \
|
from jedi.inference.base_value import iterator_to_value_set, ValueSet, \
|
||||||
NO_VALUES
|
NO_VALUES
|
||||||
|
|
|
@ -255,7 +255,7 @@ class _BuiltinMappedMethod(ValueWrapper):
|
||||||
|
|
||||||
def py__call__(self, arguments):
|
def py__call__(self, arguments):
|
||||||
# TODO add TypeError if params are given/or not correct.
|
# TODO add TypeError if params are given/or not correct.
|
||||||
return self._method(self._value)
|
return self._method(self._value, arguments)
|
||||||
|
|
||||||
|
|
||||||
class SpecialMethodFilter(DictFilter):
|
class SpecialMethodFilter(DictFilter):
|
||||||
|
@ -330,7 +330,7 @@ class _AttributeOverwriteMixin(object):
|
||||||
def get_filters(self, *args, **kwargs):
|
def get_filters(self, *args, **kwargs):
|
||||||
yield SpecialMethodFilter(self, self.overwritten_methods, self._wrapped_value)
|
yield SpecialMethodFilter(self, self.overwritten_methods, self._wrapped_value)
|
||||||
|
|
||||||
for filter in self._wrapped_value.get_filters():
|
for filter in self._wrapped_value.get_filters(*args, **kwargs):
|
||||||
yield filter
|
yield filter
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ from parso import ParserSyntaxError, parse
|
||||||
from jedi._compatibility import force_unicode, Parameter
|
from jedi._compatibility import force_unicode, Parameter
|
||||||
from jedi.inference.cache import inference_state_method_cache
|
from jedi.inference.cache import inference_state_method_cache
|
||||||
from jedi.inference.base_value import ValueSet, NO_VALUES
|
from jedi.inference.base_value import ValueSet, NO_VALUES
|
||||||
from jedi.inference.gradual.base import DefineGenericBase, GenericClass
|
from jedi.inference.gradual.base import DefineGenericBaseClass, GenericClass
|
||||||
from jedi.inference.gradual.generics import TupleGenericManager
|
from jedi.inference.gradual.generics import TupleGenericManager
|
||||||
from jedi.inference.gradual.type_var import TypeVar
|
from jedi.inference.gradual.type_var import TypeVar
|
||||||
from jedi.inference.helpers import is_string
|
from jedi.inference.helpers import is_string
|
||||||
|
@ -229,7 +229,7 @@ def infer_return_types(function, arguments):
|
||||||
|
|
||||||
return ValueSet.from_sets(
|
return ValueSet.from_sets(
|
||||||
ann.define_generics(type_var_dict)
|
ann.define_generics(type_var_dict)
|
||||||
if isinstance(ann, (DefineGenericBase, TypeVar)) else ValueSet({ann})
|
if isinstance(ann, (DefineGenericBaseClass, TypeVar)) else ValueSet({ann})
|
||||||
for ann in annotation_values
|
for ann in annotation_values
|
||||||
).execute_annotation()
|
).execute_annotation()
|
||||||
|
|
||||||
|
@ -276,17 +276,17 @@ def infer_return_for_callable(arguments, param_values, result_values):
|
||||||
all_type_vars = {}
|
all_type_vars = {}
|
||||||
for pv in param_values:
|
for pv in param_values:
|
||||||
if pv.array_type == 'list':
|
if pv.array_type == 'list':
|
||||||
type_var_dict = infer_type_vars_for_callable(arguments, pv.py__iter__())
|
type_var_dict = _infer_type_vars_for_callable(arguments, pv.py__iter__())
|
||||||
all_type_vars.update(type_var_dict)
|
all_type_vars.update(type_var_dict)
|
||||||
|
|
||||||
return ValueSet.from_sets(
|
return ValueSet.from_sets(
|
||||||
v.define_generics(all_type_vars)
|
v.define_generics(all_type_vars)
|
||||||
if isinstance(v, (DefineGenericBase, TypeVar)) else ValueSet({v})
|
if isinstance(v, (DefineGenericBaseClass, TypeVar)) else ValueSet({v})
|
||||||
for v in result_values
|
for v in result_values
|
||||||
).execute_annotation()
|
).execute_annotation()
|
||||||
|
|
||||||
|
|
||||||
def infer_type_vars_for_callable(arguments, lazy_params):
|
def _infer_type_vars_for_callable(arguments, lazy_params):
|
||||||
"""
|
"""
|
||||||
Infers type vars for the Calllable class:
|
Infers type vars for the Calllable class:
|
||||||
|
|
||||||
|
@ -350,7 +350,7 @@ def merge_pairwise_generics(annotation_value, annotated_argument_class):
|
||||||
|
|
||||||
type_var_dict = {}
|
type_var_dict = {}
|
||||||
|
|
||||||
if not isinstance(annotated_argument_class, DefineGenericBase):
|
if not isinstance(annotated_argument_class, DefineGenericBaseClass):
|
||||||
return type_var_dict
|
return type_var_dict
|
||||||
|
|
||||||
annotation_generics = annotation_value.get_generics()
|
annotation_generics = annotation_value.get_generics()
|
||||||
|
@ -359,12 +359,7 @@ def merge_pairwise_generics(annotation_value, annotated_argument_class):
|
||||||
for annotation_generics_set, actual_generic_set in zip(annotation_generics, actual_generics):
|
for annotation_generics_set, actual_generic_set in zip(annotation_generics, actual_generics):
|
||||||
merge_type_var_dicts(
|
merge_type_var_dicts(
|
||||||
type_var_dict,
|
type_var_dict,
|
||||||
annotation_generics_set.infer_type_vars(
|
annotation_generics_set.infer_type_vars(actual_generic_set.execute_annotation()),
|
||||||
actual_generic_set,
|
|
||||||
# This is a note to ourselves that we have already
|
|
||||||
# converted the instance representation to its class.
|
|
||||||
is_class_value=True,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return type_var_dict
|
return type_var_dict
|
||||||
|
|
|
@ -23,8 +23,8 @@ class _BoundTypeVarName(AbstractNameDefinition):
|
||||||
def iter_():
|
def iter_():
|
||||||
for value in self._value_set:
|
for value in self._value_set:
|
||||||
# Replace any with the constraints if they are there.
|
# Replace any with the constraints if they are there.
|
||||||
from jedi.inference.gradual.typing import Any
|
from jedi.inference.gradual.typing import AnyClass
|
||||||
if isinstance(value, Any):
|
if isinstance(value, AnyClass):
|
||||||
for constraint in self._type_var.constraints:
|
for constraint in self._type_var.constraints:
|
||||||
yield constraint
|
yield constraint
|
||||||
else:
|
else:
|
||||||
|
@ -81,7 +81,7 @@ class _AnnotatedClassContext(ClassContext):
|
||||||
yield self._value.get_type_var_filter()
|
yield self._value.get_type_var_filter()
|
||||||
|
|
||||||
|
|
||||||
class DefineGenericBase(LazyValueWrapper):
|
class DefineGenericBaseClass(LazyValueWrapper):
|
||||||
def __init__(self, generics_manager):
|
def __init__(self, generics_manager):
|
||||||
self._generics_manager = generics_manager
|
self._generics_manager = generics_manager
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ class DefineGenericBase(LazyValueWrapper):
|
||||||
for generic_set in self.get_generics():
|
for generic_set in self.get_generics():
|
||||||
values = NO_VALUES
|
values = NO_VALUES
|
||||||
for generic in generic_set:
|
for generic in generic_set:
|
||||||
if isinstance(generic, (GenericClass, TypeVar)):
|
if isinstance(generic, (DefineGenericBaseClass, TypeVar)):
|
||||||
result = generic.define_generics(type_var_dict)
|
result = generic.define_generics(type_var_dict)
|
||||||
values |= result
|
values |= result
|
||||||
if result != ValueSet({generic}):
|
if result != ValueSet({generic}):
|
||||||
|
@ -119,7 +119,7 @@ class DefineGenericBase(LazyValueWrapper):
|
||||||
)])
|
)])
|
||||||
|
|
||||||
def is_same_class(self, other):
|
def is_same_class(self, other):
|
||||||
if not isinstance(other, DefineGenericBase):
|
if not isinstance(other, DefineGenericBaseClass):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if self.tree_node != other.tree_node:
|
if self.tree_node != other.tree_node:
|
||||||
|
@ -138,8 +138,13 @@ class DefineGenericBase(LazyValueWrapper):
|
||||||
any(
|
any(
|
||||||
# TODO why is this ordering the correct one?
|
# TODO why is this ordering the correct one?
|
||||||
cls2.is_same_class(cls1)
|
cls2.is_same_class(cls1)
|
||||||
for cls1 in class_set1
|
# TODO I'm still not sure gather_annotation_classes is a good
|
||||||
for cls2 in class_set2
|
# idea. They are essentially here to avoid comparing Tuple <=>
|
||||||
|
# tuple and instead compare tuple <=> tuple, but at the moment
|
||||||
|
# the whole `is_same_class` and `is_sub_class` matching is just
|
||||||
|
# not in the best shape.
|
||||||
|
for cls1 in class_set1.gather_annotation_classes()
|
||||||
|
for cls2 in class_set2.gather_annotation_classes()
|
||||||
) for class_set1, class_set2 in zip(given_params1, given_params2)
|
) for class_set1, class_set2 in zip(given_params1, given_params2)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -151,7 +156,7 @@ class DefineGenericBase(LazyValueWrapper):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class GenericClass(ClassMixin, DefineGenericBase):
|
class GenericClass(DefineGenericBaseClass, ClassMixin):
|
||||||
"""
|
"""
|
||||||
A class that is defined with generics, might be something simple like:
|
A class that is defined with generics, might be something simple like:
|
||||||
|
|
||||||
|
@ -190,7 +195,7 @@ class GenericClass(ClassMixin, DefineGenericBase):
|
||||||
@to_list
|
@to_list
|
||||||
def py__bases__(self):
|
def py__bases__(self):
|
||||||
for base in self._wrapped_value.py__bases__():
|
for base in self._wrapped_value.py__bases__():
|
||||||
yield _LazyGenericBaseClass(self, base)
|
yield _LazyGenericBaseClass(self, base, self._generics_manager)
|
||||||
|
|
||||||
def _create_instance_with_generics(self, generics_manager):
|
def _create_instance_with_generics(self, generics_manager):
|
||||||
return GenericClass(self._class_value, generics_manager)
|
return GenericClass(self._class_value, generics_manager)
|
||||||
|
@ -200,29 +205,30 @@ class GenericClass(ClassMixin, DefineGenericBase):
|
||||||
return True
|
return True
|
||||||
return self._class_value.is_sub_class_of(class_value)
|
return self._class_value.is_sub_class_of(class_value)
|
||||||
|
|
||||||
def infer_type_vars(self, value_set, is_class_value=False):
|
def with_generics(self, generics_tuple):
|
||||||
|
return self._class_value.with_generics(generics_tuple)
|
||||||
|
|
||||||
|
def infer_type_vars(self, value_set):
|
||||||
# Circular
|
# Circular
|
||||||
from jedi.inference.gradual.annotation import merge_pairwise_generics, merge_type_var_dicts
|
from jedi.inference.gradual.annotation import merge_pairwise_generics, merge_type_var_dicts
|
||||||
|
|
||||||
annotation_name = self.py__name__()
|
annotation_name = self.py__name__()
|
||||||
type_var_dict = {}
|
type_var_dict = {}
|
||||||
if annotation_name == 'Iterable' and not is_class_value:
|
if annotation_name == 'Iterable':
|
||||||
annotation_generics = self.get_generics()
|
annotation_generics = self.get_generics()
|
||||||
if annotation_generics:
|
if annotation_generics:
|
||||||
return annotation_generics[0].infer_type_vars(
|
return annotation_generics[0].infer_type_vars(
|
||||||
value_set.merge_types_of_iterate(),
|
value_set.merge_types_of_iterate(),
|
||||||
)
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Note: we need to handle the MRO _in order_, so we need to extract
|
# Note: we need to handle the MRO _in order_, so we need to extract
|
||||||
# the elements from the set first, then handle them, even if we put
|
# the elements from the set first, then handle them, even if we put
|
||||||
# them back in a set afterwards.
|
# them back in a set afterwards.
|
||||||
for py_class in value_set:
|
for py_class in value_set:
|
||||||
if not is_class_value:
|
if py_class.is_instance() and not py_class.is_compiled():
|
||||||
if py_class.is_instance() and not py_class.is_compiled():
|
py_class = py_class.get_annotated_class_object()
|
||||||
py_class = py_class.get_annotated_class_object()
|
else:
|
||||||
else:
|
continue
|
||||||
continue
|
|
||||||
|
|
||||||
if py_class.api_type != u'class':
|
if py_class.api_type != u'class':
|
||||||
# Functions & modules don't have an MRO and we're not
|
# Functions & modules don't have an MRO and we're not
|
||||||
|
@ -243,9 +249,10 @@ class GenericClass(ClassMixin, DefineGenericBase):
|
||||||
|
|
||||||
|
|
||||||
class _LazyGenericBaseClass(object):
|
class _LazyGenericBaseClass(object):
|
||||||
def __init__(self, class_value, lazy_base_class):
|
def __init__(self, class_value, lazy_base_class, generics_manager):
|
||||||
self._class_value = class_value
|
self._class_value = class_value
|
||||||
self._lazy_base_class = lazy_base_class
|
self._lazy_base_class = lazy_base_class
|
||||||
|
self._generics_manager = generics_manager
|
||||||
|
|
||||||
@iterator_to_value_set
|
@iterator_to_value_set
|
||||||
def infer(self):
|
def infer(self):
|
||||||
|
@ -258,7 +265,17 @@ class _LazyGenericBaseClass(object):
|
||||||
TupleGenericManager(tuple(self._remap_type_vars(base))),
|
TupleGenericManager(tuple(self._remap_type_vars(base))),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
yield base
|
if base.is_class_mixin():
|
||||||
|
# This case basically allows classes like `class Foo(List)`
|
||||||
|
# to be used like `Foo[int]`. The generics are not
|
||||||
|
# necessary and can be used later.
|
||||||
|
yield GenericClass.create_cached(
|
||||||
|
base.inference_state,
|
||||||
|
base,
|
||||||
|
self._generics_manager,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
yield base
|
||||||
|
|
||||||
def _remap_type_vars(self, base):
|
def _remap_type_vars(self, base):
|
||||||
from jedi.inference.gradual.type_var import TypeVar
|
from jedi.inference.gradual.type_var import TypeVar
|
||||||
|
@ -278,6 +295,9 @@ class _LazyGenericBaseClass(object):
|
||||||
new |= ValueSet([type_var])
|
new |= ValueSet([type_var])
|
||||||
yield new
|
yield new
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return '<%s: %s>' % (self.__class__.__name__, self._lazy_base_class)
|
||||||
|
|
||||||
|
|
||||||
class _GenericInstanceWrapper(ValueWrapper):
|
class _GenericInstanceWrapper(ValueWrapper):
|
||||||
def py__stop_iteration_returns(self):
|
def py__stop_iteration_returns(self):
|
||||||
|
@ -306,6 +326,8 @@ class _PseudoTreeNameClass(Value):
|
||||||
this class. Essentially this class makes it possible to goto that `Tuple`
|
this class. Essentially this class makes it possible to goto that `Tuple`
|
||||||
name, without affecting anything else negatively.
|
name, without affecting anything else negatively.
|
||||||
"""
|
"""
|
||||||
|
api_type = u'class'
|
||||||
|
|
||||||
def __init__(self, parent_context, tree_name):
|
def __init__(self, parent_context, tree_name):
|
||||||
super(_PseudoTreeNameClass, self).__init__(
|
super(_PseudoTreeNameClass, self).__init__(
|
||||||
parent_context.inference_state,
|
parent_context.inference_state,
|
||||||
|
@ -332,10 +354,9 @@ class _PseudoTreeNameClass(Value):
|
||||||
yield EmptyFilter()
|
yield EmptyFilter()
|
||||||
|
|
||||||
def py__class__(self):
|
def py__class__(self):
|
||||||
# TODO this is obviously not correct, but at least gives us a class if
|
# This might not be 100% correct, but it is good enough. The details of
|
||||||
# we have none. Some of these objects don't really have a base class in
|
# the typing library are not really an issue for Jedi.
|
||||||
# typeshed.
|
return builtin_from_name(self.inference_state, u'type')
|
||||||
return builtin_from_name(self.inference_state, u'object')
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
|
@ -365,9 +386,9 @@ class BaseTypingValue(LazyValueWrapper):
|
||||||
return '%s(%s)' % (self.__class__.__name__, self._tree_name.value)
|
return '%s(%s)' % (self.__class__.__name__, self._tree_name.value)
|
||||||
|
|
||||||
|
|
||||||
class BaseTypingValueWithGenerics(DefineGenericBase):
|
class BaseTypingClassWithGenerics(DefineGenericBaseClass):
|
||||||
def __init__(self, parent_context, tree_name, generics_manager):
|
def __init__(self, parent_context, tree_name, generics_manager):
|
||||||
super(BaseTypingValueWithGenerics, self).__init__(generics_manager)
|
super(BaseTypingClassWithGenerics, self).__init__(generics_manager)
|
||||||
self.inference_state = parent_context.inference_state
|
self.inference_state = parent_context.inference_state
|
||||||
self.parent_context = parent_context
|
self.parent_context = parent_context
|
||||||
self._tree_name = tree_name
|
self._tree_name = tree_name
|
||||||
|
@ -378,3 +399,29 @@ class BaseTypingValueWithGenerics(DefineGenericBase):
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '%s(%s%s)' % (self.__class__.__name__, self._tree_name.value,
|
return '%s(%s%s)' % (self.__class__.__name__, self._tree_name.value,
|
||||||
self._generics_manager)
|
self._generics_manager)
|
||||||
|
|
||||||
|
|
||||||
|
class BaseTypingInstance(LazyValueWrapper):
|
||||||
|
def __init__(self, parent_context, class_value, tree_name, generics_manager):
|
||||||
|
self.inference_state = class_value.inference_state
|
||||||
|
self.parent_context = parent_context
|
||||||
|
self._class_value = class_value
|
||||||
|
self._tree_name = tree_name
|
||||||
|
self._generics_manager = generics_manager
|
||||||
|
|
||||||
|
def py__class__(self):
|
||||||
|
return self._class_value
|
||||||
|
|
||||||
|
def get_annotated_class_object(self):
|
||||||
|
return self._class_value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return ValueName(self, self._tree_name)
|
||||||
|
|
||||||
|
def _get_wrapped_value(self):
|
||||||
|
object_, = builtin_from_name(self.inference_state, u'object').execute_annotation()
|
||||||
|
return object_
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return '<%s: %s>' % (self.__class__.__name__, self._generics_manager)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from jedi._compatibility import unicode, force_unicode
|
from jedi._compatibility import unicode, force_unicode
|
||||||
from jedi import debug
|
from jedi import debug
|
||||||
from jedi.inference.base_value import ValueSet, NO_VALUES
|
from jedi.inference.base_value import ValueSet, NO_VALUES, ValueWrapper
|
||||||
from jedi.inference.gradual.base import BaseTypingValue
|
from jedi.inference.gradual.base import BaseTypingValue
|
||||||
|
|
||||||
|
|
||||||
|
@ -107,11 +107,25 @@ class TypeVar(BaseTypingValue):
|
||||||
def execute_annotation(self):
|
def execute_annotation(self):
|
||||||
return self._get_classes().execute_annotation()
|
return self._get_classes().execute_annotation()
|
||||||
|
|
||||||
def infer_type_vars(self, value_set, is_class_value=False):
|
def infer_type_vars(self, value_set):
|
||||||
|
def iterate():
|
||||||
|
for v in value_set:
|
||||||
|
cls = v.py__class__()
|
||||||
|
if v.is_function() or v.is_class():
|
||||||
|
cls = TypeWrapper(cls, v)
|
||||||
|
yield cls
|
||||||
|
|
||||||
annotation_name = self.py__name__()
|
annotation_name = self.py__name__()
|
||||||
if not is_class_value:
|
return {annotation_name: ValueSet(iterate())}
|
||||||
return {annotation_name: value_set.py__class__()}
|
|
||||||
return {annotation_name: value_set}
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<%s: %s>' % (self.__class__.__name__, self.py__name__())
|
return '<%s: %s>' % (self.__class__.__name__, self.py__name__())
|
||||||
|
|
||||||
|
|
||||||
|
class TypeWrapper(ValueWrapper):
|
||||||
|
def __init__(self, wrapped_value, original_value):
|
||||||
|
super(TypeWrapper, self).__init__(wrapped_value)
|
||||||
|
self._original_value = original_value
|
||||||
|
|
||||||
|
def execute_annotation(self):
|
||||||
|
return ValueSet({self._original_value})
|
||||||
|
|
|
@ -12,6 +12,8 @@ from jedi.inference.value import ModuleValue
|
||||||
|
|
||||||
_jedi_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
_jedi_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
TYPESHED_PATH = os.path.join(_jedi_path, 'third_party', 'typeshed')
|
TYPESHED_PATH = os.path.join(_jedi_path, 'third_party', 'typeshed')
|
||||||
|
DJANGO_INIT_PATH = os.path.join(_jedi_path, 'third_party', 'django-stubs',
|
||||||
|
'django-stubs', '__init__.pyi')
|
||||||
|
|
||||||
_IMPORT_MAP = dict(
|
_IMPORT_MAP = dict(
|
||||||
_collections='collections',
|
_collections='collections',
|
||||||
|
@ -173,6 +175,13 @@ def _try_to_load_stub(inference_state, import_names, python_value_set,
|
||||||
)
|
)
|
||||||
if m is not None:
|
if m is not None:
|
||||||
return m
|
return m
|
||||||
|
if import_names[0] == 'django':
|
||||||
|
return _try_to_load_stub_from_file(
|
||||||
|
inference_state,
|
||||||
|
python_value_set,
|
||||||
|
file_io=FileIO(DJANGO_INIT_PATH),
|
||||||
|
import_names=import_names,
|
||||||
|
)
|
||||||
|
|
||||||
# 2. Try to load pyi files next to py files.
|
# 2. Try to load pyi files next to py files.
|
||||||
for c in python_value_set:
|
for c in python_value_set:
|
||||||
|
|
|
@ -17,7 +17,8 @@ from jedi.inference.arguments import repack_with_argument_clinic
|
||||||
from jedi.inference.filters import FilterWrapper
|
from jedi.inference.filters import FilterWrapper
|
||||||
from jedi.inference.names import NameWrapper, ValueName
|
from jedi.inference.names import NameWrapper, ValueName
|
||||||
from jedi.inference.value.klass import ClassMixin
|
from jedi.inference.value.klass import ClassMixin
|
||||||
from jedi.inference.gradual.base import BaseTypingValue, BaseTypingValueWithGenerics
|
from jedi.inference.gradual.base import BaseTypingValue, \
|
||||||
|
BaseTypingClassWithGenerics, BaseTypingInstance
|
||||||
from jedi.inference.gradual.type_var import TypeVarClass
|
from jedi.inference.gradual.type_var import TypeVarClass
|
||||||
from jedi.inference.gradual.generics import LazyGenericManager, TupleGenericManager
|
from jedi.inference.gradual.generics import LazyGenericManager, TupleGenericManager
|
||||||
|
|
||||||
|
@ -66,7 +67,7 @@ class TypingModuleName(NameWrapper):
|
||||||
yield TypeVarClass.create_cached(
|
yield TypeVarClass.create_cached(
|
||||||
inference_state, self.parent_context, self.tree_name)
|
inference_state, self.parent_context, self.tree_name)
|
||||||
elif name == 'Any':
|
elif name == 'Any':
|
||||||
yield Any.create_cached(
|
yield AnyClass.create_cached(
|
||||||
inference_state, self.parent_context, self.tree_name)
|
inference_state, self.parent_context, self.tree_name)
|
||||||
elif name == 'TYPE_CHECKING':
|
elif name == 'TYPE_CHECKING':
|
||||||
# This is needed for e.g. imports that are only available for type
|
# This is needed for e.g. imports that are only available for type
|
||||||
|
@ -84,7 +85,7 @@ class TypingModuleName(NameWrapper):
|
||||||
elif name == 'TypedDict':
|
elif name == 'TypedDict':
|
||||||
# TODO doesn't even exist in typeshed/typing.py, yet. But will be
|
# TODO doesn't even exist in typeshed/typing.py, yet. But will be
|
||||||
# added soon.
|
# added soon.
|
||||||
yield TypedDictBase.create_cached(
|
yield TypedDictClass.create_cached(
|
||||||
inference_state, self.parent_context, self.tree_name)
|
inference_state, self.parent_context, self.tree_name)
|
||||||
elif name in ('no_type_check', 'no_type_check_decorator'):
|
elif name in ('no_type_check', 'no_type_check_decorator'):
|
||||||
# This is not necessary, as long as we are not doing type checking.
|
# This is not necessary, as long as we are not doing type checking.
|
||||||
|
@ -100,7 +101,7 @@ class TypingModuleFilterWrapper(FilterWrapper):
|
||||||
name_wrapper_class = TypingModuleName
|
name_wrapper_class = TypingModuleName
|
||||||
|
|
||||||
|
|
||||||
class TypingValueWithIndex(BaseTypingValueWithGenerics):
|
class ProxyWithGenerics(BaseTypingClassWithGenerics):
|
||||||
def execute_annotation(self):
|
def execute_annotation(self):
|
||||||
string_name = self._tree_name.value
|
string_name = self._tree_name.value
|
||||||
|
|
||||||
|
@ -129,6 +130,7 @@ class TypingValueWithIndex(BaseTypingValueWithGenerics):
|
||||||
cls = mapped[string_name]
|
cls = mapped[string_name]
|
||||||
return ValueSet([cls(
|
return ValueSet([cls(
|
||||||
self.parent_context,
|
self.parent_context,
|
||||||
|
self,
|
||||||
self._tree_name,
|
self._tree_name,
|
||||||
generics_manager=self._generics_manager,
|
generics_manager=self._generics_manager,
|
||||||
)])
|
)])
|
||||||
|
@ -137,15 +139,33 @@ class TypingValueWithIndex(BaseTypingValueWithGenerics):
|
||||||
return ValueSet.from_sets(self._generics_manager.to_tuple())
|
return ValueSet.from_sets(self._generics_manager.to_tuple())
|
||||||
|
|
||||||
def _create_instance_with_generics(self, generics_manager):
|
def _create_instance_with_generics(self, generics_manager):
|
||||||
return TypingValueWithIndex(
|
return ProxyWithGenerics(
|
||||||
self.parent_context,
|
self.parent_context,
|
||||||
self._tree_name,
|
self._tree_name,
|
||||||
generics_manager
|
generics_manager
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def infer_type_vars(self, value_set):
|
||||||
|
annotation_generics = self.get_generics()
|
||||||
|
|
||||||
|
if not annotation_generics:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
annotation_name = self.py__name__()
|
||||||
|
if annotation_name == 'Optional':
|
||||||
|
# Optional[T] is equivalent to Union[T, None]. In Jedi unions
|
||||||
|
# are represented by members within a ValueSet, so we extract
|
||||||
|
# the T from the Optional[T] by removing the None value.
|
||||||
|
none = builtin_from_name(self.inference_state, u'None')
|
||||||
|
return annotation_generics[0].infer_type_vars(
|
||||||
|
value_set.filter(lambda x: x != none),
|
||||||
|
)
|
||||||
|
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
class ProxyTypingValue(BaseTypingValue):
|
class ProxyTypingValue(BaseTypingValue):
|
||||||
index_class = TypingValueWithIndex
|
index_class = ProxyWithGenerics
|
||||||
|
|
||||||
def with_generics(self, generics_tuple):
|
def with_generics(self, generics_tuple):
|
||||||
return self.index_class.create_cached(
|
return self.index_class.create_cached(
|
||||||
|
@ -183,11 +203,8 @@ class _TypingClassMixin(ClassMixin):
|
||||||
return ValueName(self, self._tree_name)
|
return ValueName(self, self._tree_name)
|
||||||
|
|
||||||
|
|
||||||
class TypingClassValueWithIndex(_TypingClassMixin, TypingValueWithIndex):
|
class TypingClassWithGenerics(ProxyWithGenerics, _TypingClassMixin):
|
||||||
def infer_type_vars(self, value_set, is_class_value=False):
|
def infer_type_vars(self, value_set):
|
||||||
# Circular
|
|
||||||
from jedi.inference.gradual.annotation import merge_pairwise_generics, merge_type_var_dicts
|
|
||||||
|
|
||||||
type_var_dict = {}
|
type_var_dict = {}
|
||||||
annotation_generics = self.get_generics()
|
annotation_generics = self.get_generics()
|
||||||
|
|
||||||
|
@ -196,24 +213,12 @@ class TypingClassValueWithIndex(_TypingClassMixin, TypingValueWithIndex):
|
||||||
|
|
||||||
annotation_name = self.py__name__()
|
annotation_name = self.py__name__()
|
||||||
if annotation_name == 'Type':
|
if annotation_name == 'Type':
|
||||||
if is_class_value:
|
return annotation_generics[0].infer_type_vars(
|
||||||
# This only applies if we are comparing something like
|
# This is basically a trick to avoid extra code: We execute the
|
||||||
# List[Type[int]] with Iterable[Type[int]]. First, Jedi tries to
|
# incoming classes to be able to use the normal code for type
|
||||||
# match List/Iterable. After that we will land here, because
|
# var inference.
|
||||||
# is_class_value will be True at that point. Obviously we also
|
value_set.execute_annotation(),
|
||||||
# compare below that both sides are `Type`.
|
)
|
||||||
for element in value_set:
|
|
||||||
element_name = element.py__name__()
|
|
||||||
if element_name == 'Type':
|
|
||||||
merge_type_var_dicts(
|
|
||||||
type_var_dict,
|
|
||||||
merge_pairwise_generics(self, element),
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
return annotation_generics[0].infer_type_vars(
|
|
||||||
value_set,
|
|
||||||
is_class_value=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
elif annotation_name == 'Callable':
|
elif annotation_name == 'Callable':
|
||||||
if len(annotation_generics) == 2:
|
if len(annotation_generics) == 2:
|
||||||
|
@ -223,13 +228,20 @@ class TypingClassValueWithIndex(_TypingClassMixin, TypingValueWithIndex):
|
||||||
|
|
||||||
elif annotation_name == 'Tuple':
|
elif annotation_name == 'Tuple':
|
||||||
tuple_annotation, = self.execute_annotation()
|
tuple_annotation, = self.execute_annotation()
|
||||||
return tuple_annotation.infer_type_vars(value_set, is_class_value)
|
return tuple_annotation.infer_type_vars(value_set)
|
||||||
|
|
||||||
return type_var_dict
|
return type_var_dict
|
||||||
|
|
||||||
|
def _create_instance_with_generics(self, generics_manager):
|
||||||
|
return TypingClassWithGenerics(
|
||||||
|
self.parent_context,
|
||||||
|
self._tree_name,
|
||||||
|
generics_manager
|
||||||
|
)
|
||||||
|
|
||||||
class ProxyTypingClassValue(_TypingClassMixin, ProxyTypingValue):
|
|
||||||
index_class = TypingClassValueWithIndex
|
class ProxyTypingClassValue(ProxyTypingValue, _TypingClassMixin):
|
||||||
|
index_class = TypingClassWithGenerics
|
||||||
|
|
||||||
|
|
||||||
class TypeAlias(LazyValueWrapper):
|
class TypeAlias(LazyValueWrapper):
|
||||||
|
@ -269,7 +281,7 @@ class TypeAlias(LazyValueWrapper):
|
||||||
return ValueSet([self._get_wrapped_value()])
|
return ValueSet([self._get_wrapped_value()])
|
||||||
|
|
||||||
|
|
||||||
class Callable(BaseTypingValueWithGenerics):
|
class Callable(BaseTypingInstance):
|
||||||
def py__call__(self, arguments):
|
def py__call__(self, arguments):
|
||||||
"""
|
"""
|
||||||
def x() -> Callable[[Callable[..., _T]], _T]: ...
|
def x() -> Callable[[Callable[..., _T]], _T]: ...
|
||||||
|
@ -286,7 +298,7 @@ class Callable(BaseTypingValueWithGenerics):
|
||||||
return infer_return_for_callable(arguments, param_values, result_values)
|
return infer_return_for_callable(arguments, param_values, result_values)
|
||||||
|
|
||||||
|
|
||||||
class Tuple(BaseTypingValueWithGenerics):
|
class Tuple(BaseTypingInstance):
|
||||||
def _is_homogenous(self):
|
def _is_homogenous(self):
|
||||||
# To specify a variable-length tuple of homogeneous type, Tuple[T, ...]
|
# To specify a variable-length tuple of homogeneous type, Tuple[T, ...]
|
||||||
# is used.
|
# is used.
|
||||||
|
@ -322,16 +334,23 @@ class Tuple(BaseTypingValueWithGenerics):
|
||||||
.py__getattribute__('tuple').execute_annotation()
|
.py__getattribute__('tuple').execute_annotation()
|
||||||
return tuple_
|
return tuple_
|
||||||
|
|
||||||
def infer_type_vars(self, value_set, is_class_value=False):
|
@property
|
||||||
|
def name(self):
|
||||||
|
return self._wrapped_value.name
|
||||||
|
|
||||||
|
def infer_type_vars(self, value_set):
|
||||||
# Circular
|
# Circular
|
||||||
from jedi.inference.gradual.annotation import merge_pairwise_generics, merge_type_var_dicts
|
from jedi.inference.gradual.annotation import merge_pairwise_generics, merge_type_var_dicts
|
||||||
from jedi.inference.gradual.base import GenericClass
|
|
||||||
|
value_set = value_set.filter(
|
||||||
|
lambda x: x.py__name__().lower() == 'tuple',
|
||||||
|
)
|
||||||
|
|
||||||
if self._is_homogenous():
|
if self._is_homogenous():
|
||||||
# The parameter annotation is of the form `Tuple[T, ...]`,
|
# The parameter annotation is of the form `Tuple[T, ...]`,
|
||||||
# so we treat the incoming tuple like a iterable sequence
|
# so we treat the incoming tuple like a iterable sequence
|
||||||
# rather than a positional container of elements.
|
# rather than a positional container of elements.
|
||||||
return self.get_generics()[0].infer_type_vars(
|
return self._class_value.get_generics()[0].infer_type_vars(
|
||||||
value_set.merge_types_of_iterate(),
|
value_set.merge_types_of_iterate(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -343,27 +362,32 @@ class Tuple(BaseTypingValueWithGenerics):
|
||||||
|
|
||||||
type_var_dict = {}
|
type_var_dict = {}
|
||||||
for element in value_set:
|
for element in value_set:
|
||||||
py_class = element.get_annotated_class_object()
|
try:
|
||||||
if not isinstance(py_class, GenericClass):
|
method = element.get_annotated_class_object
|
||||||
py_class = element
|
except AttributeError:
|
||||||
|
# This might still happen, because the tuple name matching
|
||||||
|
# above is not 100% correct, so just catch the remaining
|
||||||
|
# cases here.
|
||||||
|
continue
|
||||||
|
|
||||||
|
py_class = method()
|
||||||
merge_type_var_dicts(
|
merge_type_var_dicts(
|
||||||
type_var_dict,
|
type_var_dict,
|
||||||
merge_pairwise_generics(self, py_class),
|
merge_pairwise_generics(self._class_value, py_class),
|
||||||
)
|
)
|
||||||
|
|
||||||
return type_var_dict
|
return type_var_dict
|
||||||
|
|
||||||
|
|
||||||
class Generic(BaseTypingValueWithGenerics):
|
class Generic(BaseTypingInstance):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Protocol(BaseTypingValueWithGenerics):
|
class Protocol(BaseTypingInstance):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Any(BaseTypingValue):
|
class AnyClass(BaseTypingValue):
|
||||||
def execute_annotation(self):
|
def execute_annotation(self):
|
||||||
debug.warning('Used Any - returned no results')
|
debug.warning('Used Any - returned no results')
|
||||||
return NO_VALUES
|
return NO_VALUES
|
||||||
|
@ -398,6 +422,10 @@ class NewType(Value):
|
||||||
self._type_value_set = type_value_set
|
self._type_value_set = type_value_set
|
||||||
self.tree_node = tree_node
|
self.tree_node = tree_node
|
||||||
|
|
||||||
|
def py__class__(self):
|
||||||
|
c, = self._type_value_set.py__class__()
|
||||||
|
return c
|
||||||
|
|
||||||
def py__call__(self, arguments):
|
def py__call__(self, arguments):
|
||||||
return self._type_value_set.execute_annotation()
|
return self._type_value_set.execute_annotation()
|
||||||
|
|
||||||
|
@ -413,7 +441,7 @@ class CastFunction(BaseTypingValue):
|
||||||
return type_value_set.execute_annotation()
|
return type_value_set.execute_annotation()
|
||||||
|
|
||||||
|
|
||||||
class TypedDictBase(BaseTypingValue):
|
class TypedDictClass(BaseTypingValue):
|
||||||
"""
|
"""
|
||||||
This class has no responsibilities and is just here to make sure that typed
|
This class has no responsibilities and is just here to make sure that typed
|
||||||
dicts can be identified.
|
dicts can be identified.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from jedi.inference.base_value import ValueSet, NO_VALUES
|
from jedi.inference.base_value import ValueSet, NO_VALUES
|
||||||
from jedi.common.utils import monkeypatch
|
from jedi.common import monkeypatch
|
||||||
|
|
||||||
|
|
||||||
class AbstractLazyValue(object):
|
class AbstractLazyValue(object):
|
||||||
|
|
|
@ -3,13 +3,14 @@ import re
|
||||||
|
|
||||||
from parso import python_bytes_to_unicode
|
from parso import python_bytes_to_unicode
|
||||||
|
|
||||||
|
from jedi._compatibility import FileNotFoundError
|
||||||
from jedi.debug import dbg
|
from jedi.debug import dbg
|
||||||
from jedi.file_io import KnownContentFileIO
|
from jedi.file_io import KnownContentFileIO
|
||||||
from jedi.inference.imports import SubModuleName, load_module_from_path
|
from jedi.inference.imports import SubModuleName, load_module_from_path
|
||||||
from jedi.inference.filters import ParserTreeFilter
|
from jedi.inference.filters import ParserTreeFilter
|
||||||
from jedi.inference.gradual.conversion import convert_names
|
from jedi.inference.gradual.conversion import convert_names
|
||||||
|
|
||||||
_IGNORE_FOLDERS = ('.tox', 'venv', '__pycache__')
|
_IGNORE_FOLDERS = ('.tox', '.venv', 'venv', '__pycache__')
|
||||||
|
|
||||||
_OPENED_FILE_LIMIT = 2000
|
_OPENED_FILE_LIMIT = 2000
|
||||||
"""
|
"""
|
||||||
|
@ -113,7 +114,7 @@ def _find_global_variables(names, search_name):
|
||||||
yield n
|
yield n
|
||||||
|
|
||||||
|
|
||||||
def find_references(module_context, tree_name):
|
def find_references(module_context, tree_name, only_in_module=False):
|
||||||
inf = module_context.inference_state
|
inf = module_context.inference_state
|
||||||
search_name = tree_name.value
|
search_name = tree_name.value
|
||||||
|
|
||||||
|
@ -127,10 +128,14 @@ def find_references(module_context, tree_name):
|
||||||
|
|
||||||
found_names_dct = _dictionarize(found_names)
|
found_names_dct = _dictionarize(found_names)
|
||||||
|
|
||||||
module_contexts = set(d.get_root_context() for d in found_names)
|
module_contexts = [module_context]
|
||||||
module_contexts = [module_context] + [m for m in module_contexts if m != module_context]
|
if not only_in_module:
|
||||||
|
module_contexts.extend(
|
||||||
|
m for m in set(d.get_root_context() for d in found_names)
|
||||||
|
if m != module_context and m.tree_node is not None
|
||||||
|
)
|
||||||
# For param no search for other modules is necessary.
|
# For param no search for other modules is necessary.
|
||||||
if any(n.api_type == 'param' for n in found_names):
|
if only_in_module or any(n.api_type == 'param' for n in found_names):
|
||||||
potential_modules = module_contexts
|
potential_modules = module_contexts
|
||||||
else:
|
else:
|
||||||
potential_modules = get_module_contexts_containing_name(
|
potential_modules = get_module_contexts_containing_name(
|
||||||
|
@ -157,7 +162,10 @@ def find_references(module_context, tree_name):
|
||||||
else:
|
else:
|
||||||
for name in new:
|
for name in new:
|
||||||
non_matching_reference_maps.setdefault(name, []).append(new)
|
non_matching_reference_maps.setdefault(name, []).append(new)
|
||||||
return found_names_dct.values()
|
result = found_names_dct.values()
|
||||||
|
if only_in_module:
|
||||||
|
return [n for n in result if n.get_root_context() == module_context]
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def _check_fs(inference_state, file_io, regex):
|
def _check_fs(inference_state, file_io, regex):
|
||||||
|
|
|
@ -31,6 +31,25 @@ from jedi.inference.context import CompForContext
|
||||||
from jedi.inference.value.decorator import Decoratee
|
from jedi.inference.value.decorator import Decoratee
|
||||||
from jedi.plugins import plugin_manager
|
from jedi.plugins import plugin_manager
|
||||||
|
|
||||||
|
operator_to_magic_method = {
|
||||||
|
'+': '__add__',
|
||||||
|
'-': '__sub__',
|
||||||
|
'*': '__mul__',
|
||||||
|
'/': '__truediv__',
|
||||||
|
'//': '__floordiv__',
|
||||||
|
'%': '__mod__',
|
||||||
|
'**': '__pow__',
|
||||||
|
'<<': '__lshift__',
|
||||||
|
'>>': '__rshift__',
|
||||||
|
'&': '__and__',
|
||||||
|
'|': '__or__',
|
||||||
|
'^': '__xor__',
|
||||||
|
}
|
||||||
|
|
||||||
|
reverse_operator_to_magic_method = {
|
||||||
|
k: '__r' + v[2:] for k, v in operator_to_magic_method.items()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def _limit_value_infers(func):
|
def _limit_value_infers(func):
|
||||||
"""
|
"""
|
||||||
|
@ -538,12 +557,12 @@ def _is_annotation_name(name):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def _is_tuple(value):
|
|
||||||
return isinstance(value, iterable.Sequence) and value.array_type == 'tuple'
|
|
||||||
|
|
||||||
|
|
||||||
def _is_list(value):
|
def _is_list(value):
|
||||||
return isinstance(value, iterable.Sequence) and value.array_type == 'list'
|
return value.array_type == 'list'
|
||||||
|
|
||||||
|
|
||||||
|
def _is_tuple(value):
|
||||||
|
return value.array_type == 'tuple'
|
||||||
|
|
||||||
|
|
||||||
def _bool_to_value(inference_state, bool_):
|
def _bool_to_value(inference_state, bool_):
|
||||||
|
@ -584,7 +603,7 @@ def _infer_comparison_part(inference_state, context, left, operator, right):
|
||||||
elif str_operator == '+':
|
elif str_operator == '+':
|
||||||
if l_is_num and r_is_num or is_string(left) and is_string(right):
|
if l_is_num and r_is_num or is_string(left) and is_string(right):
|
||||||
return left.execute_operation(right, str_operator)
|
return left.execute_operation(right, str_operator)
|
||||||
elif _is_tuple(left) and _is_tuple(right) or _is_list(left) and _is_list(right):
|
elif _is_list(left) and _is_list(right) or _is_tuple(left) and _is_tuple(right):
|
||||||
return ValueSet([iterable.MergedArray(inference_state, (left, right))])
|
return ValueSet([iterable.MergedArray(inference_state, (left, right))])
|
||||||
elif str_operator == '-':
|
elif str_operator == '-':
|
||||||
if l_is_num and r_is_num:
|
if l_is_num and r_is_num:
|
||||||
|
@ -622,7 +641,7 @@ def _infer_comparison_part(inference_state, context, left, operator, right):
|
||||||
_bool_to_value(inference_state, True),
|
_bool_to_value(inference_state, True),
|
||||||
_bool_to_value(inference_state, False)
|
_bool_to_value(inference_state, False)
|
||||||
])
|
])
|
||||||
elif str_operator == 'in':
|
elif str_operator in ('in', 'not in'):
|
||||||
return NO_VALUES
|
return NO_VALUES
|
||||||
|
|
||||||
def check(obj):
|
def check(obj):
|
||||||
|
@ -637,6 +656,24 @@ def _infer_comparison_part(inference_state, context, left, operator, right):
|
||||||
analysis.add(context, 'type-error-operation', operator,
|
analysis.add(context, 'type-error-operation', operator,
|
||||||
message % (left, right))
|
message % (left, right))
|
||||||
|
|
||||||
|
if left.is_class() or right.is_class():
|
||||||
|
return NO_VALUES
|
||||||
|
|
||||||
|
method_name = operator_to_magic_method[str_operator]
|
||||||
|
magic_methods = left.py__getattribute__(method_name)
|
||||||
|
if magic_methods:
|
||||||
|
result = magic_methods.execute_with_values(right)
|
||||||
|
if result:
|
||||||
|
return result
|
||||||
|
|
||||||
|
if not magic_methods:
|
||||||
|
reverse_method_name = reverse_operator_to_magic_method[str_operator]
|
||||||
|
magic_methods = right.py__getattribute__(reverse_method_name)
|
||||||
|
|
||||||
|
result = magic_methods.execute_with_values(left)
|
||||||
|
if result:
|
||||||
|
return result
|
||||||
|
|
||||||
result = ValueSet([left, right])
|
result = ValueSet([left, right])
|
||||||
debug.dbg('Used operator %s resulting in %s', operator, result)
|
debug.dbg('Used operator %s resulting in %s', operator, result)
|
||||||
return result
|
return result
|
||||||
|
|
|
@ -5,7 +5,7 @@ from jedi._compatibility import unicode, force_unicode, all_suffixes
|
||||||
from jedi.inference.cache import inference_state_method_cache
|
from jedi.inference.cache import inference_state_method_cache
|
||||||
from jedi.inference.base_value import ContextualizedNode
|
from jedi.inference.base_value import ContextualizedNode
|
||||||
from jedi.inference.helpers import is_string, get_str_or_none
|
from jedi.inference.helpers import is_string, get_str_or_none
|
||||||
from jedi.common.utils import traverse_parents
|
from jedi.common import traverse_parents
|
||||||
from jedi.parser_utils import get_cached_code_lines
|
from jedi.parser_utils import get_cached_code_lines
|
||||||
from jedi.file_io import FileIO
|
from jedi.file_io import FileIO
|
||||||
from jedi import settings
|
from jedi import settings
|
||||||
|
|
|
@ -288,6 +288,11 @@ class _BaseTreeInstance(AbstractInstanceValue):
|
||||||
"""
|
"""
|
||||||
# Arguments in __get__ descriptors are obj, class.
|
# Arguments in __get__ descriptors are obj, class.
|
||||||
# `method` is the new parent of the array, don't know if that's good.
|
# `method` is the new parent of the array, don't know if that's good.
|
||||||
|
for cls in self.class_value.py__mro__():
|
||||||
|
result = cls.py__get__on_class(self, instance, class_value)
|
||||||
|
if result is not NotImplemented:
|
||||||
|
return result
|
||||||
|
|
||||||
names = self.get_function_slot_names(u'__get__')
|
names = self.get_function_slot_names(u'__get__')
|
||||||
if names:
|
if names:
|
||||||
if instance is None:
|
if instance is None:
|
||||||
|
@ -332,13 +337,14 @@ class TreeInstance(_BaseTreeInstance):
|
||||||
for signature in self.class_value.py__getattribute__('__init__').get_signatures():
|
for signature in self.class_value.py__getattribute__('__init__').get_signatures():
|
||||||
# Just take the first result, it should always be one, because we
|
# Just take the first result, it should always be one, because we
|
||||||
# control the typeshed code.
|
# control the typeshed code.
|
||||||
if not signature.matches_signature(args) \
|
funcdef = signature.value.tree_node
|
||||||
or signature.value.tree_node is None:
|
if funcdef is None or funcdef.type != 'funcdef' \
|
||||||
|
or not signature.matches_signature(args):
|
||||||
# First check if the signature even matches, if not we don't
|
# First check if the signature even matches, if not we don't
|
||||||
# need to infer anything.
|
# need to infer anything.
|
||||||
continue
|
continue
|
||||||
bound_method = BoundMethod(self, self.class_value.as_context(), signature.value)
|
bound_method = BoundMethod(self, self.class_value.as_context(), signature.value)
|
||||||
all_annotations = py__annotations__(signature.value.tree_node)
|
all_annotations = py__annotations__(funcdef)
|
||||||
type_var_dict = infer_type_vars_for_execution(bound_method, args, all_annotations)
|
type_var_dict = infer_type_vars_for_execution(bound_method, args, all_annotations)
|
||||||
if type_var_dict:
|
if type_var_dict:
|
||||||
defined, = self.class_value.define_generics(
|
defined, = self.class_value.define_generics(
|
||||||
|
|
|
@ -58,13 +58,13 @@ class GeneratorBase(LazyAttributeOverwrite, IterableMixin):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@publish_method('__iter__')
|
@publish_method('__iter__')
|
||||||
def py__iter__(self, contextualized_node=None):
|
def _iter(self, arguments):
|
||||||
return ValueSet([self])
|
return ValueSet([self])
|
||||||
|
|
||||||
@publish_method('send')
|
@publish_method('send')
|
||||||
@publish_method('next', python_version_match=2)
|
@publish_method('next', python_version_match=2)
|
||||||
@publish_method('__next__', python_version_match=3)
|
@publish_method('__next__', python_version_match=3)
|
||||||
def py__next__(self):
|
def py__next__(self, arguments):
|
||||||
return ValueSet.from_sets(lazy_value.infer() for lazy_value in self.py__iter__())
|
return ValueSet.from_sets(lazy_value.infer() for lazy_value in self.py__iter__())
|
||||||
|
|
||||||
def py__stop_iteration_returns(self):
|
def py__stop_iteration_returns(self):
|
||||||
|
@ -192,13 +192,17 @@ class Sequence(LazyAttributeOverwrite, IterableMixin):
|
||||||
def _get_generics(self):
|
def _get_generics(self):
|
||||||
return (self.merge_types_of_iterate().py__class__(),)
|
return (self.merge_types_of_iterate().py__class__(),)
|
||||||
|
|
||||||
|
@inference_state_method_cache(default=())
|
||||||
|
def _cached_generics(self):
|
||||||
|
return self._get_generics()
|
||||||
|
|
||||||
def _get_wrapped_value(self):
|
def _get_wrapped_value(self):
|
||||||
from jedi.inference.gradual.base import GenericClass
|
from jedi.inference.gradual.base import GenericClass
|
||||||
from jedi.inference.gradual.generics import TupleGenericManager
|
from jedi.inference.gradual.generics import TupleGenericManager
|
||||||
klass = compiled.builtin_from_name(self.inference_state, self.array_type)
|
klass = compiled.builtin_from_name(self.inference_state, self.array_type)
|
||||||
c, = GenericClass(
|
c, = GenericClass(
|
||||||
klass,
|
klass,
|
||||||
TupleGenericManager(self._get_generics())
|
TupleGenericManager(self._cached_generics())
|
||||||
).execute_annotation()
|
).execute_annotation()
|
||||||
return c
|
return c
|
||||||
|
|
||||||
|
@ -286,12 +290,12 @@ class DictComprehension(ComprehensionMixin, Sequence, _DictKeyMixin):
|
||||||
return ValueSet.from_sets(values for keys, values in self._iterate())
|
return ValueSet.from_sets(values for keys, values in self._iterate())
|
||||||
|
|
||||||
@publish_method('values')
|
@publish_method('values')
|
||||||
def _imitate_values(self):
|
def _imitate_values(self, arguments):
|
||||||
lazy_value = LazyKnownValues(self._dict_values())
|
lazy_value = LazyKnownValues(self._dict_values())
|
||||||
return ValueSet([FakeList(self.inference_state, [lazy_value])])
|
return ValueSet([FakeList(self.inference_state, [lazy_value])])
|
||||||
|
|
||||||
@publish_method('items')
|
@publish_method('items')
|
||||||
def _imitate_items(self):
|
def _imitate_items(self, arguments):
|
||||||
lazy_values = [
|
lazy_values = [
|
||||||
LazyKnownValue(
|
LazyKnownValue(
|
||||||
FakeTuple(
|
FakeTuple(
|
||||||
|
@ -453,12 +457,12 @@ class DictLiteralValue(_DictMixin, SequenceLiteralValue, _DictKeyMixin):
|
||||||
yield LazyKnownValues(types)
|
yield LazyKnownValues(types)
|
||||||
|
|
||||||
@publish_method('values')
|
@publish_method('values')
|
||||||
def _imitate_values(self):
|
def _imitate_values(self, arguments):
|
||||||
lazy_value = LazyKnownValues(self._dict_values())
|
lazy_value = LazyKnownValues(self._dict_values())
|
||||||
return ValueSet([FakeList(self.inference_state, [lazy_value])])
|
return ValueSet([FakeList(self.inference_state, [lazy_value])])
|
||||||
|
|
||||||
@publish_method('items')
|
@publish_method('items')
|
||||||
def _imitate_items(self):
|
def _imitate_items(self, arguments):
|
||||||
lazy_values = [
|
lazy_values = [
|
||||||
LazyKnownValue(FakeTuple(
|
LazyKnownValue(FakeTuple(
|
||||||
self.inference_state,
|
self.inference_state,
|
||||||
|
@ -548,7 +552,7 @@ class FakeDict(_DictMixin, Sequence, _DictKeyMixin):
|
||||||
return lazy_value.infer()
|
return lazy_value.infer()
|
||||||
|
|
||||||
@publish_method('values')
|
@publish_method('values')
|
||||||
def _values(self):
|
def _values(self, arguments):
|
||||||
return ValueSet([FakeTuple(
|
return ValueSet([FakeTuple(
|
||||||
self.inference_state,
|
self.inference_state,
|
||||||
[LazyKnownValues(self._dict_values())]
|
[LazyKnownValues(self._dict_values())]
|
||||||
|
|
|
@ -114,8 +114,6 @@ class ClassFilter(ParserTreeFilter):
|
||||||
if expr_stmt is not None and expr_stmt.type == 'expr_stmt':
|
if expr_stmt is not None and expr_stmt.type == 'expr_stmt':
|
||||||
annassign = expr_stmt.children[1]
|
annassign = expr_stmt.children[1]
|
||||||
if annassign.type == 'annassign':
|
if annassign.type == 'annassign':
|
||||||
# TODO this is not proper matching
|
|
||||||
|
|
||||||
# If there is an =, the variable is obviously also
|
# If there is an =, the variable is obviously also
|
||||||
# defined on the class.
|
# defined on the class.
|
||||||
if 'ClassVar' not in annassign.children[1].get_code() \
|
if 'ClassVar' not in annassign.children[1].get_code() \
|
||||||
|
@ -135,7 +133,10 @@ class ClassMixin(object):
|
||||||
def is_class(self):
|
def is_class(self):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def py__call__(self, arguments=None):
|
def is_class_mixin(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def py__call__(self, arguments):
|
||||||
from jedi.inference.value import TreeInstance
|
from jedi.inference.value import TreeInstance
|
||||||
|
|
||||||
from jedi.inference.gradual.typing import TypedDict
|
from jedi.inference.gradual.typing import TypedDict
|
||||||
|
@ -186,11 +187,13 @@ class ClassMixin(object):
|
||||||
mro.append(cls_new)
|
mro.append(cls_new)
|
||||||
yield cls_new
|
yield cls_new
|
||||||
|
|
||||||
def get_filters(self, origin_scope=None, is_instance=False):
|
def get_filters(self, origin_scope=None, is_instance=False,
|
||||||
metaclasses = self.get_metaclasses()
|
include_metaclasses=True, include_type_when_class=True):
|
||||||
if metaclasses:
|
if include_metaclasses:
|
||||||
for f in self.get_metaclass_filters(metaclasses):
|
metaclasses = self.get_metaclasses()
|
||||||
yield f
|
if metaclasses:
|
||||||
|
for f in self.get_metaclass_filters(metaclasses, is_instance):
|
||||||
|
yield f # Python 2..
|
||||||
|
|
||||||
for cls in self.py__mro__():
|
for cls in self.py__mro__():
|
||||||
if cls.is_compiled():
|
if cls.is_compiled():
|
||||||
|
@ -202,7 +205,7 @@ class ClassMixin(object):
|
||||||
origin_scope=origin_scope,
|
origin_scope=origin_scope,
|
||||||
is_instance=is_instance
|
is_instance=is_instance
|
||||||
)
|
)
|
||||||
if not is_instance:
|
if not is_instance and include_type_when_class:
|
||||||
from jedi.inference.compiled import builtin_from_name
|
from jedi.inference.compiled import builtin_from_name
|
||||||
type_ = builtin_from_name(self.inference_state, u'type')
|
type_ = builtin_from_name(self.inference_state, u'type')
|
||||||
assert isinstance(type_, ClassValue)
|
assert isinstance(type_, ClassValue)
|
||||||
|
@ -224,6 +227,11 @@ class ClassMixin(object):
|
||||||
# Since calling staticmethod without a function is illegal, the Jedi
|
# Since calling staticmethod without a function is illegal, the Jedi
|
||||||
# plugin doesn't return anything. Therefore call directly and get what
|
# plugin doesn't return anything. Therefore call directly and get what
|
||||||
# we want: An instance of staticmethod.
|
# we want: An instance of staticmethod.
|
||||||
|
metaclasses = self.get_metaclasses()
|
||||||
|
if metaclasses:
|
||||||
|
sigs = self.get_metaclass_signatures(metaclasses)
|
||||||
|
if sigs:
|
||||||
|
return sigs
|
||||||
args = ValuesArguments([])
|
args = ValuesArguments([])
|
||||||
init_funcs = self.py__call__(args).py__getattribute__('__init__')
|
init_funcs = self.py__call__(args).py__getattribute__('__init__')
|
||||||
return [sig.bind(self) for sig in init_funcs.get_signatures()]
|
return [sig.bind(self) for sig in init_funcs.get_signatures()]
|
||||||
|
@ -240,7 +248,7 @@ class ClassMixin(object):
|
||||||
def is_typeddict(self):
|
def is_typeddict(self):
|
||||||
# TODO Do a proper mro resolution. Currently we are just listing
|
# TODO Do a proper mro resolution. Currently we are just listing
|
||||||
# classes. However, it's a complicated algorithm.
|
# classes. However, it's a complicated algorithm.
|
||||||
from jedi.inference.gradual.typing import TypedDictBase
|
from jedi.inference.gradual.typing import TypedDictClass
|
||||||
for lazy_cls in self.py__bases__():
|
for lazy_cls in self.py__bases__():
|
||||||
if not isinstance(lazy_cls, LazyTreeValue):
|
if not isinstance(lazy_cls, LazyTreeValue):
|
||||||
return False
|
return False
|
||||||
|
@ -252,7 +260,7 @@ class ClassMixin(object):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
for cls in lazy_cls.infer():
|
for cls in lazy_cls.infer():
|
||||||
if isinstance(cls, TypedDictBase):
|
if isinstance(cls, TypedDictClass):
|
||||||
return True
|
return True
|
||||||
try:
|
try:
|
||||||
method = cls.is_typeddict
|
method = cls.is_typeddict
|
||||||
|
@ -266,6 +274,52 @@ class ClassMixin(object):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def py__getitem__(self, index_value_set, contextualized_node):
|
||||||
|
from jedi.inference.gradual.base import GenericClass
|
||||||
|
if not index_value_set:
|
||||||
|
debug.warning('Class indexes inferred to nothing. Returning class instead')
|
||||||
|
return ValueSet([self])
|
||||||
|
return ValueSet(
|
||||||
|
GenericClass(
|
||||||
|
self,
|
||||||
|
LazyGenericManager(
|
||||||
|
context_of_index=contextualized_node.context,
|
||||||
|
index_value=index_value,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
for index_value in index_value_set
|
||||||
|
)
|
||||||
|
|
||||||
|
def with_generics(self, generics_tuple):
|
||||||
|
from jedi.inference.gradual.base import GenericClass
|
||||||
|
return GenericClass(
|
||||||
|
self,
|
||||||
|
TupleGenericManager(generics_tuple)
|
||||||
|
)
|
||||||
|
|
||||||
|
def define_generics(self, type_var_dict):
|
||||||
|
from jedi.inference.gradual.base import GenericClass
|
||||||
|
|
||||||
|
def remap_type_vars():
|
||||||
|
"""
|
||||||
|
The TypeVars in the resulting classes have sometimes different names
|
||||||
|
and we need to check for that, e.g. a signature can be:
|
||||||
|
|
||||||
|
def iter(iterable: Iterable[_T]) -> Iterator[_T]: ...
|
||||||
|
|
||||||
|
However, the iterator is defined as Iterator[_T_co], which means it has
|
||||||
|
a different type var name.
|
||||||
|
"""
|
||||||
|
for type_var in self.list_type_vars():
|
||||||
|
yield type_var_dict.get(type_var.py__name__(), NO_VALUES)
|
||||||
|
|
||||||
|
if type_var_dict:
|
||||||
|
return ValueSet([GenericClass(
|
||||||
|
self,
|
||||||
|
TupleGenericManager(tuple(remap_type_vars()))
|
||||||
|
)])
|
||||||
|
return ValueSet({self})
|
||||||
|
|
||||||
|
|
||||||
class ClassValue(use_metaclass(CachedMetaClass, ClassMixin, FunctionAndClassBase)):
|
class ClassValue(use_metaclass(CachedMetaClass, ClassMixin, FunctionAndClassBase)):
|
||||||
api_type = u'class'
|
api_type = u'class'
|
||||||
|
@ -310,54 +364,9 @@ class ClassValue(use_metaclass(CachedMetaClass, ClassMixin, FunctionAndClassBase
|
||||||
self.inference_state.builtins_module.py__getattribute__('object')
|
self.inference_state.builtins_module.py__getattribute__('object')
|
||||||
)]
|
)]
|
||||||
|
|
||||||
def py__getitem__(self, index_value_set, contextualized_node):
|
|
||||||
from jedi.inference.gradual.base import GenericClass
|
|
||||||
if not index_value_set:
|
|
||||||
return ValueSet([self])
|
|
||||||
return ValueSet(
|
|
||||||
GenericClass(
|
|
||||||
self,
|
|
||||||
LazyGenericManager(
|
|
||||||
context_of_index=contextualized_node.context,
|
|
||||||
index_value=index_value,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
for index_value in index_value_set
|
|
||||||
)
|
|
||||||
|
|
||||||
def with_generics(self, generics_tuple):
|
|
||||||
from jedi.inference.gradual.base import GenericClass
|
|
||||||
return GenericClass(
|
|
||||||
self,
|
|
||||||
TupleGenericManager(generics_tuple)
|
|
||||||
)
|
|
||||||
|
|
||||||
def define_generics(self, type_var_dict):
|
|
||||||
from jedi.inference.gradual.base import GenericClass
|
|
||||||
|
|
||||||
def remap_type_vars():
|
|
||||||
"""
|
|
||||||
The TypeVars in the resulting classes have sometimes different names
|
|
||||||
and we need to check for that, e.g. a signature can be:
|
|
||||||
|
|
||||||
def iter(iterable: Iterable[_T]) -> Iterator[_T]: ...
|
|
||||||
|
|
||||||
However, the iterator is defined as Iterator[_T_co], which means it has
|
|
||||||
a different type var name.
|
|
||||||
"""
|
|
||||||
for type_var in self.list_type_vars():
|
|
||||||
yield type_var_dict.get(type_var.py__name__(), NO_VALUES)
|
|
||||||
|
|
||||||
if type_var_dict:
|
|
||||||
return ValueSet([GenericClass(
|
|
||||||
self,
|
|
||||||
TupleGenericManager(tuple(remap_type_vars()))
|
|
||||||
)])
|
|
||||||
return ValueSet({self})
|
|
||||||
|
|
||||||
@plugin_manager.decorate()
|
@plugin_manager.decorate()
|
||||||
def get_metaclass_filters(self, metaclass):
|
def get_metaclass_filters(self, metaclasses, is_instance):
|
||||||
debug.dbg('Unprocessed metaclass %s', metaclass)
|
debug.warning('Unprocessed metaclass %s', metaclasses)
|
||||||
return []
|
return []
|
||||||
|
|
||||||
@inference_state_method_cache(default=NO_VALUES)
|
@inference_state_method_cache(default=NO_VALUES)
|
||||||
|
@ -377,3 +386,7 @@ class ClassValue(use_metaclass(CachedMetaClass, ClassMixin, FunctionAndClassBase
|
||||||
if values:
|
if values:
|
||||||
return values
|
return values
|
||||||
return NO_VALUES
|
return NO_VALUES
|
||||||
|
|
||||||
|
@plugin_manager.decorate()
|
||||||
|
def get_metaclass_signatures(self, metaclasses):
|
||||||
|
return []
|
||||||
|
|
|
@ -288,6 +288,8 @@ def cut_value_at_position(leaf, position):
|
||||||
column = position[1]
|
column = position[1]
|
||||||
if leaf.line == position[0]:
|
if leaf.line == position[0]:
|
||||||
column -= leaf.column
|
column -= leaf.column
|
||||||
|
if not lines:
|
||||||
|
return ''
|
||||||
lines[-1] = lines[-1][:column]
|
lines[-1] = lines[-1][:column]
|
||||||
return ''.join(lines)
|
return ''.join(lines)
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@ This is not a plugin, this is just the place were plugins are registered.
|
||||||
from jedi.plugins import stdlib
|
from jedi.plugins import stdlib
|
||||||
from jedi.plugins import flask
|
from jedi.plugins import flask
|
||||||
from jedi.plugins import pytest
|
from jedi.plugins import pytest
|
||||||
|
from jedi.plugins import django
|
||||||
from jedi.plugins import plugin_manager
|
from jedi.plugins import plugin_manager
|
||||||
|
|
||||||
|
|
||||||
plugin_manager.register(stdlib, flask, pytest)
|
plugin_manager.register(stdlib, flask, pytest, django)
|
||||||
|
|
|
@ -16,7 +16,7 @@ from jedi._compatibility import force_unicode, Parameter
|
||||||
from jedi import debug
|
from jedi import debug
|
||||||
from jedi.inference.utils import safe_property
|
from jedi.inference.utils import safe_property
|
||||||
from jedi.inference.helpers import get_str_or_none
|
from jedi.inference.helpers import get_str_or_none
|
||||||
from jedi.inference.arguments import \
|
from jedi.inference.arguments import iterate_argument_clinic, ParamIssue, \
|
||||||
repack_with_argument_clinic, AbstractArguments, TreeArgumentsWrapper
|
repack_with_argument_clinic, AbstractArguments, TreeArgumentsWrapper
|
||||||
from jedi.inference import analysis
|
from jedi.inference import analysis
|
||||||
from jedi.inference import compiled
|
from jedi.inference import compiled
|
||||||
|
@ -143,7 +143,7 @@ def _follow_param(inference_state, arguments, index):
|
||||||
return lazy_value.infer()
|
return lazy_value.infer()
|
||||||
|
|
||||||
|
|
||||||
def argument_clinic(string, want_value=False, want_context=False,
|
def argument_clinic(clinic_string, want_value=False, want_context=False,
|
||||||
want_arguments=False, want_inference_state=False,
|
want_arguments=False, want_inference_state=False,
|
||||||
want_callback=False):
|
want_callback=False):
|
||||||
"""
|
"""
|
||||||
|
@ -151,13 +151,15 @@ def argument_clinic(string, want_value=False, want_context=False,
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def f(func):
|
def f(func):
|
||||||
@repack_with_argument_clinic(string, keep_arguments_param=True,
|
def wrapper(value, arguments, callback):
|
||||||
keep_callback_param=True)
|
try:
|
||||||
def wrapper(value, *args, **kwargs):
|
args = tuple(iterate_argument_clinic(
|
||||||
arguments = kwargs.pop('arguments')
|
value.inference_state, arguments, clinic_string))
|
||||||
callback = kwargs.pop('callback')
|
except ParamIssue:
|
||||||
assert not kwargs # Python 2...
|
return NO_VALUES
|
||||||
|
|
||||||
debug.dbg('builtin start %s' % value, color='MAGENTA')
|
debug.dbg('builtin start %s' % value, color='MAGENTA')
|
||||||
|
kwargs = {}
|
||||||
if want_context:
|
if want_context:
|
||||||
kwargs['context'] = arguments.context
|
kwargs['context'] = arguments.context
|
||||||
if want_value:
|
if want_value:
|
||||||
|
@ -258,13 +260,12 @@ class ReversedObject(AttributeOverwrite):
|
||||||
super(ReversedObject, self).__init__(reversed_obj)
|
super(ReversedObject, self).__init__(reversed_obj)
|
||||||
self._iter_list = iter_list
|
self._iter_list = iter_list
|
||||||
|
|
||||||
@publish_method('__iter__')
|
def py__iter__(self, contextualized_node):
|
||||||
def py__iter__(self, contextualized_node=None):
|
|
||||||
return self._iter_list
|
return self._iter_list
|
||||||
|
|
||||||
@publish_method('next', python_version_match=2)
|
@publish_method('next', python_version_match=2)
|
||||||
@publish_method('__next__', python_version_match=3)
|
@publish_method('__next__', python_version_match=3)
|
||||||
def py__next__(self):
|
def py__next__(self, arguments):
|
||||||
return ValueSet.from_sets(
|
return ValueSet.from_sets(
|
||||||
lazy_value.infer() for lazy_value in self._iter_list
|
lazy_value.infer() for lazy_value in self._iter_list
|
||||||
)
|
)
|
||||||
|
@ -393,13 +394,13 @@ class PropertyObject(AttributeOverwrite, ValueWrapper):
|
||||||
|
|
||||||
def py__get__(self, instance, class_value):
|
def py__get__(self, instance, class_value):
|
||||||
if instance is None:
|
if instance is None:
|
||||||
return NO_VALUES
|
return ValueSet([self])
|
||||||
return self._function.execute_with_values(instance)
|
return self._function.execute_with_values(instance)
|
||||||
|
|
||||||
@publish_method('deleter')
|
@publish_method('deleter')
|
||||||
@publish_method('getter')
|
@publish_method('getter')
|
||||||
@publish_method('setter')
|
@publish_method('setter')
|
||||||
def _return_self(self):
|
def _return_self(self, arguments):
|
||||||
return ValueSet({self})
|
return ValueSet({self})
|
||||||
|
|
||||||
|
|
||||||
|
@ -516,6 +517,8 @@ class PartialObject(ValueWrapper):
|
||||||
|
|
||||||
class PartialMethodObject(PartialObject):
|
class PartialMethodObject(PartialObject):
|
||||||
def py__get__(self, instance, class_value):
|
def py__get__(self, instance, class_value):
|
||||||
|
if instance is None:
|
||||||
|
return ValueSet([self])
|
||||||
return ValueSet([PartialObject(self._actual_value, self._arguments, instance)])
|
return ValueSet([PartialObject(self._actual_value, self._arguments, instance)])
|
||||||
|
|
||||||
|
|
||||||
|
@ -782,6 +785,9 @@ _implemented = {
|
||||||
# Therefore, just make it return nothing, which leads to the stubs
|
# Therefore, just make it return nothing, which leads to the stubs
|
||||||
# being used instead. This only matters for 3.7+.
|
# being used instead. This only matters for 3.7+.
|
||||||
'_alias': lambda value, arguments, callback: NO_VALUES,
|
'_alias': lambda value, arguments, callback: NO_VALUES,
|
||||||
|
# runtime_checkable doesn't really change anything and is just
|
||||||
|
# adding logs for infering stuff, so we can safely ignore it.
|
||||||
|
'runtime_checkable': lambda value, arguments, callback: NO_VALUES,
|
||||||
},
|
},
|
||||||
'dataclasses': {
|
'dataclasses': {
|
||||||
# For now this works at least better than Jedi trying to understand it.
|
# For now this works at least better than Jedi trying to understand it.
|
||||||
|
@ -797,7 +803,7 @@ _implemented = {
|
||||||
|
|
||||||
|
|
||||||
def get_metaclass_filters(func):
|
def get_metaclass_filters(func):
|
||||||
def wrapper(cls, metaclasses):
|
def wrapper(cls, metaclasses, is_instance):
|
||||||
for metaclass in metaclasses:
|
for metaclass in metaclasses:
|
||||||
if metaclass.py__name__() == 'EnumMeta' \
|
if metaclass.py__name__() == 'EnumMeta' \
|
||||||
and metaclass.get_root_context().py__name__() == 'enum':
|
and metaclass.get_root_context().py__name__() == 'enum':
|
||||||
|
@ -805,7 +811,7 @@ def get_metaclass_filters(func):
|
||||||
return [DictFilter({
|
return [DictFilter({
|
||||||
name.string_name: EnumInstance(cls, name).name for name in filter_.values()
|
name.string_name: EnumInstance(cls, name).name for name in filter_.values()
|
||||||
})]
|
})]
|
||||||
return func(cls, metaclasses)
|
return func(cls, metaclasses, is_instance)
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -69,8 +69,8 @@ Adds an opening bracket after a function for completions.
|
||||||
# ----------------
|
# ----------------
|
||||||
|
|
||||||
if platform.system().lower() == 'windows':
|
if platform.system().lower() == 'windows':
|
||||||
_cache_directory = os.path.join(os.getenv('APPDATA') or '~', 'Jedi',
|
_cache_directory = os.path.join(os.getenv('LOCALAPPDATA') or
|
||||||
'Jedi')
|
os.path.expanduser('~'), 'Jedi', 'Jedi')
|
||||||
elif platform.system().lower() == 'darwin':
|
elif platform.system().lower() == 'darwin':
|
||||||
_cache_directory = os.path.join('~', 'Library', 'Caches', 'Jedi')
|
_cache_directory = os.path.join('~', 'Library', 'Caches', 'Jedi')
|
||||||
else:
|
else:
|
||||||
|
@ -81,7 +81,7 @@ cache_directory = os.path.expanduser(_cache_directory)
|
||||||
The path where the cache is stored.
|
The path where the cache is stored.
|
||||||
|
|
||||||
On Linux, this defaults to ``~/.cache/jedi/``, on OS X to
|
On Linux, this defaults to ``~/.cache/jedi/``, on OS X to
|
||||||
``~/Library/Caches/Jedi/`` and on Windows to ``%APPDATA%\\Jedi\\Jedi\\``.
|
``~/Library/Caches/Jedi/`` and on Windows to ``%LOCALAPPDATA%\\Jedi\\Jedi\\``.
|
||||||
On Linux, if the environment variable ``$XDG_CACHE_HOME`` is set,
|
On Linux, if the environment variable ``$XDG_CACHE_HOME`` is set,
|
||||||
``$XDG_CACHE_HOME/jedi`` is used instead of the default one.
|
``$XDG_CACHE_HOME/jedi`` is used instead of the default one.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
import sys, types, os;has_mfs = sys.version_info > (3, 5);p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('mpl_toolkits',));importlib = has_mfs and __import__('importlib.util');has_mfs and __import__('importlib.machinery');m = has_mfs and sys.modules.setdefault('mpl_toolkits', importlib.util.module_from_spec(importlib.machinery.PathFinder.find_spec('mpl_toolkits', [os.path.dirname(p)])));m = m or sys.modules.setdefault('mpl_toolkits', types.ModuleType('mpl_toolkits'));mp = (m or []) and m.__dict__.setdefault('__path__',[]);(p not in mp) and mp.append(p)
|
|
|
@ -1 +0,0 @@
|
||||||
pip
|
|
|
@ -1,127 +0,0 @@
|
||||||
Metadata-Version: 2.1
|
|
||||||
Name: matplotlib
|
|
||||||
Version: 3.2.1
|
|
||||||
Summary: Python plotting package
|
|
||||||
Home-page: https://matplotlib.org
|
|
||||||
Author: John D. Hunter, Michael Droettboom
|
|
||||||
Author-email: matplotlib-users@python.org
|
|
||||||
License: PSF
|
|
||||||
Download-URL: https://matplotlib.org/users/installing.html
|
|
||||||
Project-URL: Documentation, https://matplotlib.org
|
|
||||||
Project-URL: Source Code, https://github.com/matplotlib/matplotlib
|
|
||||||
Project-URL: Bug Tracker, https://github.com/matplotlib/matplotlib/issues
|
|
||||||
Project-URL: Forum, https://discourse.matplotlib.org/
|
|
||||||
Project-URL: Donate, https://numfocus.org/donate-to-matplotlib
|
|
||||||
Platform: any
|
|
||||||
Classifier: Development Status :: 5 - Production/Stable
|
|
||||||
Classifier: Framework :: Matplotlib
|
|
||||||
Classifier: Intended Audience :: Science/Research
|
|
||||||
Classifier: Intended Audience :: Education
|
|
||||||
Classifier: License :: OSI Approved :: Python Software Foundation License
|
|
||||||
Classifier: Programming Language :: Python
|
|
||||||
Classifier: Programming Language :: Python :: 3
|
|
||||||
Classifier: Programming Language :: Python :: 3.6
|
|
||||||
Classifier: Programming Language :: Python :: 3.7
|
|
||||||
Classifier: Programming Language :: Python :: 3.8
|
|
||||||
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
||||||
Requires-Python: >=3.6
|
|
||||||
Description-Content-Type: text/x-rst
|
|
||||||
Requires-Dist: cycler (>=0.10)
|
|
||||||
Requires-Dist: kiwisolver (>=1.0.1)
|
|
||||||
Requires-Dist: numpy (>=1.11)
|
|
||||||
Requires-Dist: pyparsing (!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1)
|
|
||||||
Requires-Dist: python-dateutil (>=2.1)
|
|
||||||
|
|
||||||
|Travis|_ |AzurePipelines|_ |AppVeyor|_ |Codecov|_ |LGTM|_ |PyPi|_ |Gitter|_ |NUMFocus|_ |GitTutorial|_
|
|
||||||
|
|
||||||
|
|
||||||
.. |Travis| image:: https://travis-ci.org/matplotlib/matplotlib.svg?branch=master
|
|
||||||
.. _Travis: https://travis-ci.org/matplotlib/matplotlib
|
|
||||||
|
|
||||||
.. |AzurePipelines| image:: https://dev.azure.com/matplotlib/matplotlib/_apis/build/status/matplotlib.matplotlib?branchName=master
|
|
||||||
.. _AzurePipelines: https://dev.azure.com/matplotlib/matplotlib/_build/latest?definitionId=1&branchName=master
|
|
||||||
|
|
||||||
.. |AppVeyor| image:: https://ci.appveyor.com/api/projects/status/github/matplotlib/matplotlib?branch=master&svg=true
|
|
||||||
.. _AppVeyor: https://ci.appveyor.com/project/matplotlib/matplotlib
|
|
||||||
|
|
||||||
.. |Codecov| image:: https://codecov.io/github/matplotlib/matplotlib/badge.svg?branch=master&service=github
|
|
||||||
.. _Codecov: https://codecov.io/github/matplotlib/matplotlib?branch=master
|
|
||||||
|
|
||||||
.. |LGTM| image:: https://img.shields.io/lgtm/grade/python/g/matplotlib/matplotlib.svg?logo=lgtm&logoWidth=18
|
|
||||||
.. _LGTM: https://lgtm.com/projects/g/matplotlib/matplotlib
|
|
||||||
|
|
||||||
.. |PyPi| image:: https://badge.fury.io/py/matplotlib.svg
|
|
||||||
.. _PyPi: https://badge.fury.io/py/matplotlib
|
|
||||||
|
|
||||||
.. |Gitter| image:: https://badges.gitter.im/matplotlib/matplotlib.png
|
|
||||||
.. _Gitter: https://gitter.im/matplotlib/matplotlib
|
|
||||||
|
|
||||||
.. |NUMFocus| image:: https://img.shields.io/badge/powered%20by-NumFOCUS-orange.svg?style=flat&colorA=E1523D&colorB=007D8A
|
|
||||||
.. _NUMFocus: https://www.numfocus.org
|
|
||||||
|
|
||||||
.. |GitTutorial| image:: https://img.shields.io/badge/PR-Welcome-%23FF8300.svg?
|
|
||||||
.. _GitTutorial: https://git-scm.com/book/en/v2/GitHub-Contributing-to-a-Project
|
|
||||||
|
|
||||||
.. image:: https://matplotlib.org/_static/logo2.svg
|
|
||||||
|
|
||||||
|
|
||||||
Matplotlib is a comprehensive library for creating static, animated, and interactive visualizations in Python.
|
|
||||||
|
|
||||||
Check out our `home page <https://matplotlib.org/>`_ for more information.
|
|
||||||
|
|
||||||
.. image:: https://matplotlib.org/_static/readme_preview.png
|
|
||||||
|
|
||||||
Matplotlib produces publication-quality figures in a variety of hardcopy formats
|
|
||||||
and interactive environments across platforms. Matplotlib can be used in Python scripts,
|
|
||||||
the Python and IPython shell, web application servers, and various
|
|
||||||
graphical user interface toolkits.
|
|
||||||
|
|
||||||
|
|
||||||
Install
|
|
||||||
=======
|
|
||||||
|
|
||||||
For installation instructions and requirements, see `INSTALL.rst <INSTALL.rst>`_ or the
|
|
||||||
`install <https://matplotlib.org/users/installing.html>`_ documentation.
|
|
||||||
|
|
||||||
Test
|
|
||||||
====
|
|
||||||
|
|
||||||
After installation, launch the test suite::
|
|
||||||
|
|
||||||
python -m pytest
|
|
||||||
|
|
||||||
Read the `testing guide <https://matplotlib.org/devel/testing.html>`_ for more information and alternatives.
|
|
||||||
|
|
||||||
Contribute
|
|
||||||
==========
|
|
||||||
You've discovered a bug or something else you want to change - excellent!
|
|
||||||
|
|
||||||
You've worked out a way to fix it – even better!
|
|
||||||
|
|
||||||
You want to tell us about it – best of all!
|
|
||||||
|
|
||||||
Start at the `contributing guide <https://matplotlib.org/devdocs/devel/contributing.html>`_!
|
|
||||||
|
|
||||||
Contact
|
|
||||||
=======
|
|
||||||
|
|
||||||
`Discourse <https://discourse.matplotlib.org/>`_ is the discussion forum for general questions and discussions and our recommended starting point.
|
|
||||||
|
|
||||||
Our active mailing lists (which are mirrored on Discourse) are:
|
|
||||||
|
|
||||||
* `Users <https://mail.python.org/mailman/listinfo/matplotlib-users>`_ mailing list: matplotlib-users@python.org
|
|
||||||
* `Announcement <https://mail.python.org/mailman/listinfo/matplotlib-announce>`_ mailing list: matplotlib-announce@python.org
|
|
||||||
* `Development <https://mail.python.org/mailman/listinfo/matplotlib-devel>`_ mailing list: matplotlib-devel@python.org
|
|
||||||
|
|
||||||
Gitter_ is for coordinating development and asking questions directly related
|
|
||||||
to contributing to matplotlib.
|
|
||||||
|
|
||||||
|
|
||||||
Citing Matplotlib
|
|
||||||
=================
|
|
||||||
If Matplotlib contributes to a project that leads to publication, please
|
|
||||||
acknowledge this by citing Matplotlib.
|
|
||||||
|
|
||||||
`A ready-made citation entry <https://matplotlib.org/citing.html>`_ is available.
|
|
||||||
|
|
||||||
|
|
|
@ -1,892 +0,0 @@
|
||||||
__pycache__/pylab.cpython-37.pyc,,
|
|
||||||
matplotlib-3.2.1-py3.7-nspkg.pth,sha256=FgO_3ug071EXEKT8mgOPBUhyrswPtPCYjOpUCyau7UU,569
|
|
||||||
matplotlib-3.2.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
|
||||||
matplotlib-3.2.1.dist-info/METADATA,sha256=F1oGQTHWb-ltDWNhlYUpDR9UvF5wAQ7l9pyVaRKk_1M,5170
|
|
||||||
matplotlib-3.2.1.dist-info/RECORD,,
|
|
||||||
matplotlib-3.2.1.dist-info/WHEEL,sha256=AhV6RMqZ2IDfreRJKo44QWYxYeP-0Jr0bezzBLQ1eog,109
|
|
||||||
matplotlib-3.2.1.dist-info/namespace_packages.txt,sha256=A2PHFg9NKYOU4pEQ1h97U0Qd-rB-65W34XqC-56ZN9g,13
|
|
||||||
matplotlib-3.2.1.dist-info/top_level.txt,sha256=9tEw2ni8DdgX8CceoYHqSH1s50vrJ9SDfgtLIG8e3Y4,30
|
|
||||||
matplotlib/.libs/libpng16-cfdb1654.so.16.21.0,sha256=Fo8LBDWTuCclLkpSng_KP5pI7wcQtuXA9opT1FFkXl0,275648
|
|
||||||
matplotlib/.libs/libz-a147dcb0.so.1.2.3,sha256=VwXH3AM7bnoa793tKDw_H0pW-VZos08-FEtM_g_VWVM,87848
|
|
||||||
matplotlib/__init__.py,sha256=FLEIOOmlbJDBzqg4aq8W6w0wSpQF9tVwGu0VW8EwqsA,54615
|
|
||||||
matplotlib/__pycache__/__init__.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/_animation_data.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/_cm.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/_cm_listed.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/_color_data.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/_constrained_layout.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/_layoutbox.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/_mathtext_data.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/_pylab_helpers.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/_text_layout.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/_version.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/afm.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/animation.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/artist.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/axis.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/backend_bases.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/backend_managers.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/backend_tools.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/bezier.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/blocking_input.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/category.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/cm.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/collections.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/colorbar.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/colors.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/container.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/contour.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/dates.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/docstring.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/dviread.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/figure.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/font_manager.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/fontconfig_pattern.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/gridspec.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/hatch.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/image.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/legend.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/legend_handler.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/lines.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/markers.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/mathtext.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/mlab.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/offsetbox.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/patches.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/path.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/patheffects.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/pylab.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/pyplot.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/quiver.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/rcsetup.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/sankey.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/scale.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/spines.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/stackplot.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/streamplot.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/table.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/texmanager.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/text.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/textpath.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/ticker.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/tight_bbox.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/tight_layout.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/transforms.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/type1font.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/units.cpython-37.pyc,,
|
|
||||||
matplotlib/__pycache__/widgets.cpython-37.pyc,,
|
|
||||||
matplotlib/_animation_data.py,sha256=yClmMx6K-y6pjG3FdHancRyRhyneFuBEbQZ_lhezVys,7499
|
|
||||||
matplotlib/_cm.py,sha256=nZCQdTWsPc5aJ-n08l2g293Wwg0kSWIgcfStzv9Dtxg,66643
|
|
||||||
matplotlib/_cm_listed.py,sha256=9aMZ1uoTkxeDKlXfUNmY99HEtAXsW_JcSpwYaBs0kHs,98165
|
|
||||||
matplotlib/_color_data.py,sha256=K2HSKblmuh-X_1ZZ9TcXcP7iKHaGC4mC_ScWqX_tdXE,34947
|
|
||||||
matplotlib/_constrained_layout.py,sha256=eafuhM2rw5SL_ilqf0ImxQwtmFX_pR_boeKUrjTHvB0,29678
|
|
||||||
matplotlib/_contour.cpython-37m-x86_64-linux-gnu.so,sha256=DRPfZh8e5HSbyEOFKEIzpA_3hYpnxckV0Icfe-g-wyM,95144
|
|
||||||
matplotlib/_image.cpython-37m-x86_64-linux-gnu.so,sha256=Cqh9lTOtqGFawWjs6bJtIPDu8vVhWxKGh_eOWwNuC4M,242496
|
|
||||||
matplotlib/_layoutbox.py,sha256=LG5KEmNm5apZa1putqzafEpX9w4lLwkoOPxg4owiO2Y,23872
|
|
||||||
matplotlib/_mathtext_data.py,sha256=CmKFRW6mXCJqgZSQaiNOSG_VUn9WiSx5Hrg-4qKIn14,89371
|
|
||||||
matplotlib/_path.cpython-37m-x86_64-linux-gnu.so,sha256=KJKK6xVyb6Mf-68Ff7BkdnDzRqjY6YTt8WMeCktMA_Q,190280
|
|
||||||
matplotlib/_png.cpython-37m-x86_64-linux-gnu.so,sha256=cDH1KkEt0zaDGkU8YS3JZcIOX3mmMYiXHQeoqnHMKqM,35608
|
|
||||||
matplotlib/_pylab_helpers.py,sha256=RscVbvWEk6QyznzVvX-lSHkWCUOo9Lik7D7j4xelQJ4,3445
|
|
||||||
matplotlib/_qhull.cpython-37m-x86_64-linux-gnu.so,sha256=BpI08RX7LTHpLVupETP7x1ZXRLaovGizekhFuXR4MFE,382672
|
|
||||||
matplotlib/_text_layout.py,sha256=88DxzfAOPzpRjpu0OwLaRl6eOVJ5Var8ZxrDyhAQ7C8,1036
|
|
||||||
matplotlib/_tri.cpython-37m-x86_64-linux-gnu.so,sha256=4GFgZW6QzC-_k3oVs0UCjYnnL0hDSVGIqPIKuTCq2UU,128616
|
|
||||||
matplotlib/_version.py,sha256=etxeX_ByADCJBN53WhU2IEezakT1gixcO41qmDlMwfY,471
|
|
||||||
matplotlib/afm.py,sha256=Y2FmLqutIXI__QiAbMNpFclleQrpGf1xsqBgjyCZir0,16642
|
|
||||||
matplotlib/animation.py,sha256=N0HzAqLF1fscM2OIkER3gv4zsqUXWpxA8BmE_3Jqi5k,68066
|
|
||||||
matplotlib/artist.py,sha256=2Qd4EUb9n4FAizD1fdb48diR7yRivgwvY8JESg4r4mE,53229
|
|
||||||
matplotlib/axes/__init__.py,sha256=npQuBvs_xEBEGUP2-BBZzCrelsAQYgB1U96kSZTSWIs,46
|
|
||||||
matplotlib/axes/__pycache__/__init__.cpython-37.pyc,,
|
|
||||||
matplotlib/axes/__pycache__/_axes.cpython-37.pyc,,
|
|
||||||
matplotlib/axes/__pycache__/_base.cpython-37.pyc,,
|
|
||||||
matplotlib/axes/__pycache__/_secondary_axes.cpython-37.pyc,,
|
|
||||||
matplotlib/axes/__pycache__/_subplots.cpython-37.pyc,,
|
|
||||||
matplotlib/axes/_axes.py,sha256=dSaGhVBB00lKf1AF9mCsaFcleTU8qKlSkVNP2ET_CPU,312519
|
|
||||||
matplotlib/axes/_base.py,sha256=x89D4ElapqkI9lQ0oTAwTGcKPm-m-J26Fg-A0R3Ys1M,159726
|
|
||||||
matplotlib/axes/_secondary_axes.py,sha256=plMlrvrznuuBSRakuznyCyr_ZNnSiuc_3J-YD3Hg8e8,14352
|
|
||||||
matplotlib/axes/_subplots.py,sha256=rkT6vCCbCTItY_oAmlT-1rSPOoIerjScJC91I2YLTp0,10203
|
|
||||||
matplotlib/axis.py,sha256=50zN9IvoaYGqq8t8zUiaaTtcUJeNjxdAnmXioRlfNWc,90049
|
|
||||||
matplotlib/backend_bases.py,sha256=vNzjru0RDGIlzyeT9vjmWv8ktEFaax0C7W1tXz1qR_w,117888
|
|
||||||
matplotlib/backend_managers.py,sha256=HuHOXPFjVF1R6ttBLxlucsLcEsWlRXtbm_wr1OJer2Q,12819
|
|
||||||
matplotlib/backend_tools.py,sha256=zVBxfyPoQx0_lQe1Su0o-zTycOQt-zKWTp3HEY-jTxI,36252
|
|
||||||
matplotlib/backends/__init__.py,sha256=cKAeiC5g0Up9svoxT24paOcnKc4tb5cbfbF-AWxXLUE,1722
|
|
||||||
matplotlib/backends/__pycache__/__init__.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/__pycache__/_backend_pdf_ps.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/__pycache__/_backend_tk.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/__pycache__/backend_agg.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/__pycache__/backend_cairo.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/__pycache__/backend_gtk3.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/__pycache__/backend_gtk3agg.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/__pycache__/backend_gtk3cairo.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/__pycache__/backend_macosx.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/__pycache__/backend_mixed.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/__pycache__/backend_nbagg.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/__pycache__/backend_pdf.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/__pycache__/backend_pgf.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/__pycache__/backend_ps.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/__pycache__/backend_qt4.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/__pycache__/backend_qt4agg.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/__pycache__/backend_qt4cairo.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/__pycache__/backend_qt5.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/__pycache__/backend_qt5agg.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/__pycache__/backend_qt5cairo.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/__pycache__/backend_svg.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/__pycache__/backend_template.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/__pycache__/backend_tkagg.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/__pycache__/backend_tkcairo.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/__pycache__/backend_webagg.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/__pycache__/backend_webagg_core.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/__pycache__/backend_wx.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/__pycache__/backend_wxagg.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/__pycache__/backend_wxcairo.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/__pycache__/qt_compat.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/_backend_agg.cpython-37m-x86_64-linux-gnu.so,sha256=6sGDDe5csQINH5pB6bcFhLK0a8SyPrVFBT7pUAE4J0s,362384
|
|
||||||
matplotlib/backends/_backend_pdf_ps.py,sha256=T8x_NWAo9_Wvnpw6HnsneRI9AyAxcp80TDe-z2eosbM,2709
|
|
||||||
matplotlib/backends/_backend_tk.py,sha256=k1eZjNeVC0rDMEKlOqevga-PFTERv9mcwUn_d_LZUyo,32021
|
|
||||||
matplotlib/backends/_tkagg.cpython-37m-x86_64-linux-gnu.so,sha256=dk5Ggr6xNaIkdXEind0il3BBX2zEnZTQwzdAVD-wE0U,27256
|
|
||||||
matplotlib/backends/backend_agg.py,sha256=bjt43QEsQ-AeEeWXSBwRcbJsuDU7Dex-JsdbApekXzA,22347
|
|
||||||
matplotlib/backends/backend_cairo.py,sha256=zJAQ5_OkKchNrItE8jN9CriAw4aQ0PP3qKqfINu3CSc,16562
|
|
||||||
matplotlib/backends/backend_gtk3.py,sha256=ED_iXiCIXQlMJmh8YlJJcPkCxnm9Wly7kSod0UogtRc,33832
|
|
||||||
matplotlib/backends/backend_gtk3agg.py,sha256=iKLBQ48c9Vh4krSxYeSDbHZ4G9wXoezk2VTIgNR4BWw,3072
|
|
||||||
matplotlib/backends/backend_gtk3cairo.py,sha256=TDQUuYq5KCPvAU-MY2wBxpx2zAn9vOO_ieeE_7fdtS4,1591
|
|
||||||
matplotlib/backends/backend_macosx.py,sha256=fALNUVEkZrqRrMHe5G_wy5i7FODvXXIum7RU2PXOiG4,5829
|
|
||||||
matplotlib/backends/backend_mixed.py,sha256=R3-Z5AW7anq31csMjylsY4pSehsAsBLrxFD5YhZkZ6w,5280
|
|
||||||
matplotlib/backends/backend_nbagg.py,sha256=xAv_OZfz6NtMrbAXWqwX9GCgTEsb5e5FpyAMHSIE-j4,8902
|
|
||||||
matplotlib/backends/backend_pdf.py,sha256=sq_dTpmyOkYrtWdHQGKanZxRezXFmfeZNCMcObJR95A,96197
|
|
||||||
matplotlib/backends/backend_pgf.py,sha256=R34xfvJyVm0k4IgjCHPU0bKeP02zJ0_Pr0hV6yaCVv8,43431
|
|
||||||
matplotlib/backends/backend_ps.py,sha256=MWZmgx9nrlp9_u50gp_JZE2bEt2E3ixZxPqT9Wk5BqY,50575
|
|
||||||
matplotlib/backends/backend_qt4.py,sha256=H9AsG4NAF27LdGUJDi1n5RwJhK1lI43sa9VXtUgW3K8,397
|
|
||||||
matplotlib/backends/backend_qt4agg.py,sha256=BXMTBYmqyT_uvEpgSMWts5m2q1YK0vhPeybt0ZMVd0I,292
|
|
||||||
matplotlib/backends/backend_qt4cairo.py,sha256=cvXKhk8CZvceDiEl9OXmumjJ6dZ3k0u93xy8w8i24gQ,229
|
|
||||||
matplotlib/backends/backend_qt5.py,sha256=BjGTvVXytXhqRPpYNzoWaO03ULCfKdF3xG78e9nr0Sc,39256
|
|
||||||
matplotlib/backends/backend_qt5agg.py,sha256=sF1oFyKNmOAdCGUChUbrKfmFmNo8QuD2SzuQQl4U0Mg,3560
|
|
||||||
matplotlib/backends/backend_qt5cairo.py,sha256=YzXN1Ckr6JLS2r50LPxeypajdWccXaHoXC5QZ4VWrEY,1892
|
|
||||||
matplotlib/backends/backend_svg.py,sha256=KGdJMf-cXIW82s0MC9-wOsmtEeo8P3np_uK06z2FGkI,43552
|
|
||||||
matplotlib/backends/backend_template.py,sha256=SVPx4bl2n0eKgEolfJH7ljJnqlak0XhFE6Zr3yr6GU4,8407
|
|
||||||
matplotlib/backends/backend_tkagg.py,sha256=WMslLWYmtxlmAaBH4tx4HjmRDWMKiSV91KHF9yeMRng,676
|
|
||||||
matplotlib/backends/backend_tkcairo.py,sha256=dVCh7ZD_2OR0DBQ0N3icD8cDV1SeEzCsRja446wWhPw,1069
|
|
||||||
matplotlib/backends/backend_webagg.py,sha256=NtP1VSSXQNvB_EBQi14No7flt1C64VwekiTG58tt7LU,10794
|
|
||||||
matplotlib/backends/backend_webagg_core.py,sha256=u026hAuD_dwL0a2D7g--jzBr_KFS5UqJdFZDvIdlmII,17558
|
|
||||||
matplotlib/backends/backend_wx.py,sha256=O606ybHYiOFCxpnhpZ_TYaHdULG53YuAZQDq70xjoms,66672
|
|
||||||
matplotlib/backends/backend_wxagg.py,sha256=Jhb24f2W6e5yCqSi4F971hor_I8Epf_WMfutq3VoTYI,3027
|
|
||||||
matplotlib/backends/backend_wxcairo.py,sha256=VC5TyJaX8TPLSgHv5ckAreoGrY_KiNRMQjVInMLlcFk,1843
|
|
||||||
matplotlib/backends/qt_compat.py,sha256=Me6QS6xk4ASjOdBhr7RxvIp4Frzbdmu7mIXRO5uJlwU,6551
|
|
||||||
matplotlib/backends/qt_editor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
||||||
matplotlib/backends/qt_editor/__pycache__/__init__.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/qt_editor/__pycache__/_formlayout.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/qt_editor/__pycache__/figureoptions.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/qt_editor/__pycache__/formlayout.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/qt_editor/__pycache__/formsubplottool.cpython-37.pyc,,
|
|
||||||
matplotlib/backends/qt_editor/_formlayout.py,sha256=aHC33AfwtVjly7sPjLTFrVABZqAD2RAloR6KCEAUv5A,20592
|
|
||||||
matplotlib/backends/qt_editor/figureoptions.py,sha256=YySx6A_wZSACMEHbXYkoQ6wR0_6PPwON2c6YwejUeVs,9481
|
|
||||||
matplotlib/backends/qt_editor/formlayout.py,sha256=ERfmFwpvhl168PWNTJ0SFhQmPuSrmjzFNOe_puUCoSE,177
|
|
||||||
matplotlib/backends/qt_editor/formsubplottool.py,sha256=HiiXkwCotra_hI9JU208KOs8Q9JuGH1uAW3mV5l3Evg,1934
|
|
||||||
matplotlib/backends/web_backend/all_figures.html,sha256=m20aQIhuI4GBdrgZg_j02zSVjAcTRUufPOMSe4i7ayc,1525
|
|
||||||
matplotlib/backends/web_backend/css/boilerplate.css,sha256=qui16QXRnQFNJDbcMasfH6KtN9hLjv8883U9cJmsVCE,2310
|
|
||||||
matplotlib/backends/web_backend/css/fbm.css,sha256=Us0osu_rK8EUAdp_GXrh89tN_hUNCN-r7N1T1NvmmwI,1473
|
|
||||||
matplotlib/backends/web_backend/css/page.css,sha256=Djf6ZNMFaM6_hVaizSkDFoqk-jn81qgduwles4AroGk,1599
|
|
||||||
matplotlib/backends/web_backend/ipython_inline_figure.html,sha256=mzi-yWg4fcO6PdtTBCfiNuvcv04T53lcRQi-8hphwuE,1305
|
|
||||||
matplotlib/backends/web_backend/jquery-ui-1.12.1/AUTHORS.txt,sha256=W2Lh1mbGo3Owc0oXX9U1-TFVSZYaC72KvSRrrRp3UII,12660
|
|
||||||
matplotlib/backends/web_backend/jquery-ui-1.12.1/LICENSE.txt,sha256=3jP7aViA0LB2FdS4b3jNQ3lpBpWa3l_f73CWiCeg23g,1817
|
|
||||||
matplotlib/backends/web_backend/jquery-ui-1.12.1/external/jquery/jquery.js,sha256=Qw82-bXyGq6MydymqBxNPYTaUXXq7c8v3CwiYwLLNXU,293430
|
|
||||||
matplotlib/backends/web_backend/jquery-ui-1.12.1/images/ui-icons_444444_256x240.png,sha256=6vfH7idHJ13abFPnMaENsaexX0-7RuG2nWuyBWvJ_YE,7006
|
|
||||||
matplotlib/backends/web_backend/jquery-ui-1.12.1/images/ui-icons_555555_256x240.png,sha256=XQQFHf2dLXQDVUBPmKaD0ewP6y_KfXblM8Gm5c6S3S4,7074
|
|
||||||
matplotlib/backends/web_backend/jquery-ui-1.12.1/images/ui-icons_777620_256x240.png,sha256=nb5KDQP-7W9l6yVgoKi0ukJkVF7o_THBdjo7IZ0DKNY,4676
|
|
||||||
matplotlib/backends/web_backend/jquery-ui-1.12.1/images/ui-icons_777777_256x240.png,sha256=51snIR4W_PlHFRaAAbtwVco3bUb5KBELo9CCUjJFLlo,7013
|
|
||||||
matplotlib/backends/web_backend/jquery-ui-1.12.1/images/ui-icons_cc0000_256x240.png,sha256=AokVddQ1jp7d4-QtlAV_jp-CqdZDdvce6GzvFJ0wU34,4632
|
|
||||||
matplotlib/backends/web_backend/jquery-ui-1.12.1/images/ui-icons_ffffff_256x240.png,sha256=trBt7vK5JMw4NdY_SIPUeIJzSjPnGyEtkXpozt47jp0,6313
|
|
||||||
matplotlib/backends/web_backend/jquery-ui-1.12.1/index.html,sha256=5g7_MLZlkh92FXWOR0q02My8knssXq20DXz-BkiYiP4,32588
|
|
||||||
matplotlib/backends/web_backend/jquery-ui-1.12.1/jquery-ui.css,sha256=p6xU9YulB7E2Ic62_PX-h59ayb3PBJ0WFTEQxq0EjHw,37326
|
|
||||||
matplotlib/backends/web_backend/jquery-ui-1.12.1/jquery-ui.js,sha256=T0Vest3yCU7pafRw9r-settMBX6JkKN06dqBnpQ8d30,520714
|
|
||||||
matplotlib/backends/web_backend/jquery-ui-1.12.1/jquery-ui.min.css,sha256=rByPlHULObEjJ6XQxW_flG2r-22R5dKiAoef-aXWfik,32076
|
|
||||||
matplotlib/backends/web_backend/jquery-ui-1.12.1/jquery-ui.min.js,sha256=KM512VNnjElC30ehFwehXjx1YCHPiQkOPmqnrWtpccM,253669
|
|
||||||
matplotlib/backends/web_backend/jquery-ui-1.12.1/jquery-ui.structure.css,sha256=E1uqV-d412nbSI-oqDMIQsTSttP-FS7Bxwc7mQdQYOo,18705
|
|
||||||
matplotlib/backends/web_backend/jquery-ui-1.12.1/jquery-ui.structure.min.css,sha256=rxais37anKUnpL5QzSYte-JnIsmkGmLG-ZhKSkZkwVM,15548
|
|
||||||
matplotlib/backends/web_backend/jquery-ui-1.12.1/jquery-ui.theme.css,sha256=mEMD30TTg-vIEGUmHHgcgSOgm0FBfLipyQ97Jr0TTH8,18671
|
|
||||||
matplotlib/backends/web_backend/jquery-ui-1.12.1/jquery-ui.theme.min.css,sha256=AjyoyaRtnGVTywKH_Isxxu5PXI0s4CcE0BzPAX83Ppc,13849
|
|
||||||
matplotlib/backends/web_backend/jquery-ui-1.12.1/package.json,sha256=kjEW8xMYuqRSwEE58KqTDNLgkx_6YL7tb1M9vlMK98w,1847
|
|
||||||
matplotlib/backends/web_backend/js/mpl.js,sha256=xrBOaet7K2P2iq7wgIexceDdc9T_WFb4TPJXDX55JuU,16991
|
|
||||||
matplotlib/backends/web_backend/js/mpl_tornado.js,sha256=lSxC7-yqF1GYY-6SheaHanx6SujMdcG7Vx2_3qbi-9Q,272
|
|
||||||
matplotlib/backends/web_backend/js/nbagg_mpl.js,sha256=nqIF0zFBQGpOo5Tmq2uRkyFJDeali66PWQDSYySgpnQ,7428
|
|
||||||
matplotlib/backends/web_backend/nbagg_uat.ipynb,sha256=y1N8hQzBJ05rJ2hZla2_Mw6tOUfNP1UHKo636W1e098,15933
|
|
||||||
matplotlib/backends/web_backend/single_figure.html,sha256=-iFrlIsaY1rOK9bNiDxcX8fdc0WP7DXXq-MEuLYfOvM,1216
|
|
||||||
matplotlib/bezier.py,sha256=Fqb2gqRnmS2wYjEZVFcdSngRxh5g_hFnxX82RFpimec,17271
|
|
||||||
matplotlib/blocking_input.py,sha256=soMcLeXT2mKxkH5fyQqYEOP_Dd-TUjoA1_L7imb2B2Q,11105
|
|
||||||
matplotlib/category.py,sha256=_iJbNlZzi3kqPtz_bhEBCj8q6RsBp5Urd3yNS81dOQg,7131
|
|
||||||
matplotlib/cbook/__init__.py,sha256=k7_Gdpbg26mrQlfQJr3eTnRGvXInhfuEjWeBrY5-IlY,70426
|
|
||||||
matplotlib/cbook/__pycache__/__init__.cpython-37.pyc,,
|
|
||||||
matplotlib/cbook/__pycache__/deprecation.cpython-37.pyc,,
|
|
||||||
matplotlib/cbook/deprecation.py,sha256=E8xSJYv-br0VswU-LNQFTU0VlurdH6v2rNOMCvOfs2I,15080
|
|
||||||
matplotlib/cm.py,sha256=qo1ZhJvKa7dCfALcj1X6rsy7R60pbJht7zK6pi_9EcA,12623
|
|
||||||
matplotlib/collections.py,sha256=n_Mru2nfEhqvAGHAD3g_JhWAoxvtK5MjYFLfztvSK3s,74328
|
|
||||||
matplotlib/colorbar.py,sha256=gaI17iRKX4NntEaLROYsg4q1fXUboda2L0w7PUaWSKg,63074
|
|
||||||
matplotlib/colors.py,sha256=auWiOGPMdI5twHSoVVI0AyEe7O9LJfn3fKetp_8yMzA,75537
|
|
||||||
matplotlib/compat/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
||||||
matplotlib/compat/__pycache__/__init__.cpython-37.pyc,,
|
|
||||||
matplotlib/container.py,sha256=yAq9s8ylaQxkt2N-qTSnBdF7zQZ5_-g96XgKzlySaLI,4302
|
|
||||||
matplotlib/contour.py,sha256=p8PJvj7N7wd-yA94NP7cz230VHmYG3rkSsdYSoTP4hE,68387
|
|
||||||
matplotlib/dates.py,sha256=hGrXqJ-O1ahP2yCYK0HjFWJu0jt-EDke1S33VZ2uOe0,66867
|
|
||||||
matplotlib/docstring.py,sha256=TuDl6xhQwCISvIV5_rPKvT85V1k1IA5HVSyK-JMY9k4,3970
|
|
||||||
matplotlib/dviread.py,sha256=sO5Mq6CkNYqgu5S3oMcDc6Gqh1YhD36VoRWH9PbbIJw,39009
|
|
||||||
matplotlib/figure.py,sha256=yQsOCdFl3HHez8H3Y6xylSKAAEZzy-Hl-b1-BSJ3r8k,100886
|
|
||||||
matplotlib/font_manager.py,sha256=OZ2BAmPgFrO4VjeBA-DKGM0H0I5T4ev5gtAdirbXwR0,45282
|
|
||||||
matplotlib/fontconfig_pattern.py,sha256=El7xTXT3EnEESVONX9bKz_Yvaq4lLQp3KIYBgNbAguI,6719
|
|
||||||
matplotlib/ft2font.cpython-37m-x86_64-linux-gnu.so,sha256=titw2vLp_Ik6oZW2WqHUe-BXW8d7U1vIQgiAQEyWqgg,919008
|
|
||||||
matplotlib/gridspec.py,sha256=k_YO0Enho4Ztxi9-rv-ZgSXs-rrqKq1TdeOGwOzJwQI,25046
|
|
||||||
matplotlib/hatch.py,sha256=6AcnVeBs4d_Uv_FWQoU48v28iW5F7oKI_RKkv68L_WM,6971
|
|
||||||
matplotlib/image.py,sha256=0FR_I8bEV0XfM6kYyAS8j965LCbtapgnpxDWLrEV390,62787
|
|
||||||
matplotlib/legend.py,sha256=QBSq0VyGWFsTB7QFGx8bpmUR-MLw9xJPrhMcJSlpVtU,48268
|
|
||||||
matplotlib/legend_handler.py,sha256=hDMDvDJepK6UUyTJCkGQcAMVgLYW7eD16hQoQNVGQFY,26428
|
|
||||||
matplotlib/lines.py,sha256=8u3vEQXb_ceOivl4zyL5MIDuVDlxgZwOsH9xf37OIYo,51362
|
|
||||||
matplotlib/markers.py,sha256=Xpuq9O1t7OB3DBK2nZa4IbPjqV0ROGY9mxXW_NUKDKk,32533
|
|
||||||
matplotlib/mathtext.py,sha256=udfWXa-87xV1Mhve65rO0jf5On3DAQwJ-FgD6BSojhM,120491
|
|
||||||
matplotlib/mlab.py,sha256=1V0nvAkZF5RJbsIAp3AfTgzim2wRQCql0FCq7HvLknI,49040
|
|
||||||
matplotlib/mpl-data/fonts/afm/cmex10.afm,sha256=blR3ERmrVBV5XKkAnDCj4NMeYVgzH7cXtJ3u59u9GuE,12070
|
|
||||||
matplotlib/mpl-data/fonts/afm/cmmi10.afm,sha256=5qwEOpedEo76bDUahyuuF1q0cD84tRrX-VQ4p3MlfBo,10416
|
|
||||||
matplotlib/mpl-data/fonts/afm/cmr10.afm,sha256=WDvgC_D3UkGJg9u-J0U6RaT02lF4oz3lQxHtg1r3lYw,10101
|
|
||||||
matplotlib/mpl-data/fonts/afm/cmsy10.afm,sha256=AbmzvCVWBceHRfmRfeJ9E6xzOQTFLk0U1zDfpf3_MaM,8295
|
|
||||||
matplotlib/mpl-data/fonts/afm/cmtt10.afm,sha256=4ji7_mTpeWMa93o_UHBWPKCnqsBfhJJNllat1lJArP4,6501
|
|
||||||
matplotlib/mpl-data/fonts/afm/pagd8a.afm,sha256=jjFrigwkTpYLqa26cpzZvKQNBo-PuF4bmDVqaM4pMWw,17183
|
|
||||||
matplotlib/mpl-data/fonts/afm/pagdo8a.afm,sha256=sgNQdeYyx8J-itGw9h31y95aMBiTCRvmNSPTXwwS7xg,17255
|
|
||||||
matplotlib/mpl-data/fonts/afm/pagk8a.afm,sha256=ZUtfHPloNqcvGMHMxaKDSlshhOcjwheUx143RwpGdIU,17241
|
|
||||||
matplotlib/mpl-data/fonts/afm/pagko8a.afm,sha256=Yj1wBg6Jsqqz1KBfhRoJ3ACR-CMQol8Fj_ZM5NZ1gDk,17346
|
|
||||||
matplotlib/mpl-data/fonts/afm/pbkd8a.afm,sha256=Zl5o6J_di9Y5j2EpHtjew-_sfg7-WoeVmO9PzOYSTUc,15157
|
|
||||||
matplotlib/mpl-data/fonts/afm/pbkdi8a.afm,sha256=JAOno930iTyfZILMf11vWtiaTgrJcPpP6FRTRhEMMD4,15278
|
|
||||||
matplotlib/mpl-data/fonts/afm/pbkl8a.afm,sha256=UJqJjOJ6xQDgDBLX157mKpohIJFVmHM-N6x2-DiGv14,15000
|
|
||||||
matplotlib/mpl-data/fonts/afm/pbkli8a.afm,sha256=AWislZ2hDbs0ox_qOWREugsbS8_8lpL48LPMR40qpi0,15181
|
|
||||||
matplotlib/mpl-data/fonts/afm/pcrb8a.afm,sha256=6j1TS2Uc7DWSc-8l42TGDc1u0Fg8JspeWfxFayjUwi8,15352
|
|
||||||
matplotlib/mpl-data/fonts/afm/pcrbo8a.afm,sha256=smg3mjl9QaBDtQIt06ko5GvaxLsO9QtTvYANuE5hfG0,15422
|
|
||||||
matplotlib/mpl-data/fonts/afm/pcrr8a.afm,sha256=7nxFr0Ehz4E5KG_zSE5SZOhxRH8MyfnCbw-7x5wu7tw,15339
|
|
||||||
matplotlib/mpl-data/fonts/afm/pcrro8a.afm,sha256=NKEz7XtdFkh9cA8MvY-S3UOZlV2Y_J3tMEWFFxj7QSg,15443
|
|
||||||
matplotlib/mpl-data/fonts/afm/phvb8a.afm,sha256=NAx4M4HjL7vANCJbc-tk04Vkol-T0oaXeQ3T2h-XUvM,17155
|
|
||||||
matplotlib/mpl-data/fonts/afm/phvb8an.afm,sha256=8e_myD-AQkNF7q9XNLb2m76_lX2TUr3a5wog_LIE1sk,17086
|
|
||||||
matplotlib/mpl-data/fonts/afm/phvbo8a.afm,sha256=8fkBRmJ-SWY2YrBg8fFyjJyrJp8daQ6JPO6LvhM8xPI,17230
|
|
||||||
matplotlib/mpl-data/fonts/afm/phvbo8an.afm,sha256=aeVRvV4r15BBvxuRJ0MG8ZHuH2HViuIiCYkvuapmkmM,17195
|
|
||||||
matplotlib/mpl-data/fonts/afm/phvl8a.afm,sha256=IyMYM-bgl-gI6rG0EuZZ2OLzlxJfGeSh8xqsh0t-eJQ,15627
|
|
||||||
matplotlib/mpl-data/fonts/afm/phvlo8a.afm,sha256=s12C-eNnIDHJ_UVbuiprjxBjCiHIbS3Y8ORTC-qTpuI,15729
|
|
||||||
matplotlib/mpl-data/fonts/afm/phvr8a.afm,sha256=Kt8KaRidts89EBIK29X2JomDUEDxvroeaJz_RNTi6r4,17839
|
|
||||||
matplotlib/mpl-data/fonts/afm/phvr8an.afm,sha256=lL5fAHTRwODl-sB5mH7IfsD1tnnea4yRUK-_Ca2bQHM,17781
|
|
||||||
matplotlib/mpl-data/fonts/afm/phvro8a.afm,sha256=3KqK3eejiR4hIFBUynuSX_4lMdE2V2T58xOF8lX-fwc,17919
|
|
||||||
matplotlib/mpl-data/fonts/afm/phvro8an.afm,sha256=Vx9rRf3YfasMY7tz-njSxz67xHKk-fNkN7yBi0X2IP0,17877
|
|
||||||
matplotlib/mpl-data/fonts/afm/pncb8a.afm,sha256=aoXepTcDQtQa_mspflMJkEFKefzXHoyjz6ioJVI0YNc,16028
|
|
||||||
matplotlib/mpl-data/fonts/afm/pncbi8a.afm,sha256=pCWW1MYgy0EmvwaYsaYJaAI_LfrsKmDANHu7Pk0RaiU,17496
|
|
||||||
matplotlib/mpl-data/fonts/afm/pncr8a.afm,sha256=0CIB2BLe9r-6_Wl5ObRTTf98UOrezmGQ8ZOuBX5kLks,16665
|
|
||||||
matplotlib/mpl-data/fonts/afm/pncri8a.afm,sha256=5R-pLZOnaHNG8pjV6MP3Ai-d2OTQYR_cYCb5zQhzfSU,16920
|
|
||||||
matplotlib/mpl-data/fonts/afm/pplb8a.afm,sha256=3EzUbNnXr5Ft5eFLY00W9oWu59rHORgDXUuJaOoKN58,15662
|
|
||||||
matplotlib/mpl-data/fonts/afm/pplbi8a.afm,sha256=X_9tVspvrcMer3OS8qvdwjFFqpAXYZneyCL2NHA902g,15810
|
|
||||||
matplotlib/mpl-data/fonts/afm/pplr8a.afm,sha256=ijMb497FDJ9nVdVMb21F7W3-cu9sb_9nF0oriFpSn8k,15752
|
|
||||||
matplotlib/mpl-data/fonts/afm/pplri8a.afm,sha256=8KITbarcUUMi_hdoRLLmNHtlqs0TtOSKqtPFft7X5nY,15733
|
|
||||||
matplotlib/mpl-data/fonts/afm/psyr.afm,sha256=Iyt8ajE4B2Tm34oBj2pKtctIf9kPfq05suQefq8p3Ro,9644
|
|
||||||
matplotlib/mpl-data/fonts/afm/ptmb8a.afm,sha256=bL1fA1NC4_nW14Zrnxz4nHlXJb4dzELJPvodqKnYeMg,17983
|
|
||||||
matplotlib/mpl-data/fonts/afm/ptmbi8a.afm,sha256=-_Ui6XlKaFTHEnkoS_-1GtIr5VtGa3gFQ2ezLOYHs08,18070
|
|
||||||
matplotlib/mpl-data/fonts/afm/ptmr8a.afm,sha256=IEcsWcmzJyjCwkgsw4o6hIMmzlyXUglJat9s1PZNnEU,17942
|
|
||||||
matplotlib/mpl-data/fonts/afm/ptmri8a.afm,sha256=49fQMg5fIGguZ7rgc_2styMK55Pv5bPTs7wCzqpcGpk,18068
|
|
||||||
matplotlib/mpl-data/fonts/afm/putb8a.afm,sha256=qMaHTdpkrNL-m4DWhjpxJCSmgYkCv1qIzLlFfM0rl40,21532
|
|
||||||
matplotlib/mpl-data/fonts/afm/putbi8a.afm,sha256=g7AVJyiTxeMpNk_1cSfmYgM09uNUfPlZyWGv3D1vcAk,21931
|
|
||||||
matplotlib/mpl-data/fonts/afm/putr8a.afm,sha256=XYmNC5GQgSVAZKTIYdYeNksE6znNm9GF_0SmQlriqx0,22148
|
|
||||||
matplotlib/mpl-data/fonts/afm/putri8a.afm,sha256=i7fVe-iLyLtQxCfAa4IxdxH-ufcHmMk7hbCGG5TxAY4,21891
|
|
||||||
matplotlib/mpl-data/fonts/afm/pzcmi8a.afm,sha256=wyuoIWEZOcoXrSl1tPzLkEahik7kGi91JJj-tkFRG4A,16250
|
|
||||||
matplotlib/mpl-data/fonts/afm/pzdr.afm,sha256=MyjLAnzKYRdQBfof1W3k_hf30MvqOkqL__G22mQ5xww,9467
|
|
||||||
matplotlib/mpl-data/fonts/pdfcorefonts/Courier-Bold.afm,sha256=sIDDI-B82VZ3C0mI_mHFITCZ7PVn37AIYMv1CrHX4sE,15333
|
|
||||||
matplotlib/mpl-data/fonts/pdfcorefonts/Courier-BoldOblique.afm,sha256=zg61QobD3YU9UBfCXmvmhBNaFKno-xj8sY0b2RpgfLw,15399
|
|
||||||
matplotlib/mpl-data/fonts/pdfcorefonts/Courier-Oblique.afm,sha256=vRQm5j1sTUN4hicT1PcVZ9P9DTTUHhEzfPXqUUzVZhE,15441
|
|
||||||
matplotlib/mpl-data/fonts/pdfcorefonts/Courier.afm,sha256=Mdcq2teZEBJrIqVXnsnhee7oZnTs6-P8_292kWGTrw4,15335
|
|
||||||
matplotlib/mpl-data/fonts/pdfcorefonts/Helvetica-Bold.afm,sha256=i2l4gcjuYXoXf28uK7yIVwuf0rnw6J7PwPVQeHj5iPw,69269
|
|
||||||
matplotlib/mpl-data/fonts/pdfcorefonts/Helvetica-BoldOblique.afm,sha256=Um5O6qK11DXLt8uj_0IoWkc84TKqHK3bObSKUswQqvY,69365
|
|
||||||
matplotlib/mpl-data/fonts/pdfcorefonts/Helvetica-Oblique.afm,sha256=hVYDg2b52kqtbVeCzmiv25bW1yYdpkZS-LXlGREN2Rs,74392
|
|
||||||
matplotlib/mpl-data/fonts/pdfcorefonts/Helvetica.afm,sha256=23cvKDD7bQAJB3kdjSahJSTZaUOppznlIO6FXGslyW8,74292
|
|
||||||
matplotlib/mpl-data/fonts/pdfcorefonts/Symbol.afm,sha256=P5UaoXr4y0qh4SiMa5uqijDT6ZDr2-jPmj1ayry593E,9740
|
|
||||||
matplotlib/mpl-data/fonts/pdfcorefonts/Times-Bold.afm,sha256=cQTmr2LFPwKQE_sGQageMcmFicjye16mKJslsJLHQyE,64251
|
|
||||||
matplotlib/mpl-data/fonts/pdfcorefonts/Times-BoldItalic.afm,sha256=pzWOdycm6RqocBWgAVY5Jq0z3Fp7LuqWgLNMx4q6OFw,59642
|
|
||||||
matplotlib/mpl-data/fonts/pdfcorefonts/Times-Italic.afm,sha256=bK5puSMpGT_YUILwyJrXoxjfj7XJOdfv5TQ_iKsJRzw,66328
|
|
||||||
matplotlib/mpl-data/fonts/pdfcorefonts/Times-Roman.afm,sha256=hhNrUnpazuDDKD1WpraPxqPWCYLrO7D7bMVOg-zI13o,60460
|
|
||||||
matplotlib/mpl-data/fonts/pdfcorefonts/ZapfDingbats.afm,sha256=ZuOmt9GcKofjdOq8kqhPhtAIhOwkL2rTJTmZxAjFakA,9527
|
|
||||||
matplotlib/mpl-data/fonts/pdfcorefonts/readme.txt,sha256=MRv8ppSITYYAb7lt5EOw9DWWNZIblfxsFhu5TQE7cpI,828
|
|
||||||
matplotlib/mpl-data/fonts/ttf/DejaVuSans-Bold.ttf,sha256=sYS4njwQdfIva3FXW2_CDUlys8_TsjMiym_Vltyu8Wc,704128
|
|
||||||
matplotlib/mpl-data/fonts/ttf/DejaVuSans-BoldOblique.ttf,sha256=bt8CgxYBhq9FHL7nHnuEXy5Mq_Jku5ks5mjIPCVGXm8,641720
|
|
||||||
matplotlib/mpl-data/fonts/ttf/DejaVuSans-Oblique.ttf,sha256=zN90s1DxH9PdV3TeUOXmNGoaXaH1t9X7g1kGZel6UhM,633840
|
|
||||||
matplotlib/mpl-data/fonts/ttf/DejaVuSans.ttf,sha256=P99pyr8GBJ6nCgC1kZNA4s4ebQKwzDxLRPtoAb0eDSI,756072
|
|
||||||
matplotlib/mpl-data/fonts/ttf/DejaVuSansDisplay.ttf,sha256=ggmdz7paqGjN_CdFGYlSX-MpL3N_s8ngMozpzvWWUvY,25712
|
|
||||||
matplotlib/mpl-data/fonts/ttf/DejaVuSansMono-Bold.ttf,sha256=uq2ppRcv4giGJRr_BDP8OEYZEtXa8HKH577lZiCo2pY,331536
|
|
||||||
matplotlib/mpl-data/fonts/ttf/DejaVuSansMono-BoldOblique.ttf,sha256=ppCBwVx2yCfgonpaf1x0thNchDSZlVSV_6jCDTqYKIs,253116
|
|
||||||
matplotlib/mpl-data/fonts/ttf/DejaVuSansMono-Oblique.ttf,sha256=KAUoE_enCfyJ9S0ZLcmV708P3Fw9e3OknWhJsZFtDNA,251472
|
|
||||||
matplotlib/mpl-data/fonts/ttf/DejaVuSansMono.ttf,sha256=YC7Ia4lIz82VZIL-ZPlMNshndwFJ7y95HUYT9EO87LM,340240
|
|
||||||
matplotlib/mpl-data/fonts/ttf/DejaVuSerif-Bold.ttf,sha256=w3U_Lta8Zz8VhG3EWt2-s7nIcvMvsY_VOiHxvvHtdnY,355692
|
|
||||||
matplotlib/mpl-data/fonts/ttf/DejaVuSerif-BoldItalic.ttf,sha256=2T7-x6nS6CZ2jRou6VuVhw4V4pWZqE80hK8d4c7C4YE,347064
|
|
||||||
matplotlib/mpl-data/fonts/ttf/DejaVuSerif-Italic.ttf,sha256=PnmU-8VPoQzjNSpC1Uj63X2crbacsRCbydlg9trFfwQ,345612
|
|
||||||
matplotlib/mpl-data/fonts/ttf/DejaVuSerif.ttf,sha256=EHJElW6ZYrnpb6zNxVGCXgrgiYrhNzcTPhuSGi_TX_o,379740
|
|
||||||
matplotlib/mpl-data/fonts/ttf/DejaVuSerifDisplay.ttf,sha256=KRTzLkfHd8J75Wd6-ufbTeefnkXeb8kJfZlJwjwU99U,14300
|
|
||||||
matplotlib/mpl-data/fonts/ttf/LICENSE_DEJAVU,sha256=11k43sCY8G8Kw8AIUwZdlPAgvhw8Yu8dwpdboVtNmw4,4816
|
|
||||||
matplotlib/mpl-data/fonts/ttf/LICENSE_STIX,sha256=cxFOZdp1AxNhXR6XxCzf5iJpNcu-APm-geOHhD-s0h8,5475
|
|
||||||
matplotlib/mpl-data/fonts/ttf/STIXGeneral.ttf,sha256=FnN4Ax4t3cYhbWeBnJJg6aBv_ExHjk4jy5im_USxg8I,448228
|
|
||||||
matplotlib/mpl-data/fonts/ttf/STIXGeneralBol.ttf,sha256=6FM9xwg_o0a9oZM9YOpKg7Z9CUW86vGzVB-CtKDixqA,237360
|
|
||||||
matplotlib/mpl-data/fonts/ttf/STIXGeneralBolIta.ttf,sha256=mHiP1LpI37sr0CbA4gokeosGxzcoeWKLemuw1bsJc2w,181152
|
|
||||||
matplotlib/mpl-data/fonts/ttf/STIXGeneralItalic.ttf,sha256=bPyzM9IrfDxiO9_UAXTxTIXD1nMcphZsHtyAFA6uhSc,175040
|
|
||||||
matplotlib/mpl-data/fonts/ttf/STIXNonUni.ttf,sha256=Ulb34CEzWsSFTRgPDovxmJZOwvyCAXYnbhaqvGU3u1c,59108
|
|
||||||
matplotlib/mpl-data/fonts/ttf/STIXNonUniBol.ttf,sha256=XRBqW3jR_8MBdFU0ObhiV7-kXwiBIMs7QVClHcT5tgs,30512
|
|
||||||
matplotlib/mpl-data/fonts/ttf/STIXNonUniBolIta.ttf,sha256=pb22DnbDf2yQqizotc3wBDqFGC_g27YcCGJivH9-Le8,41272
|
|
||||||
matplotlib/mpl-data/fonts/ttf/STIXNonUniIta.ttf,sha256=BMr9pWiBv2YIZdq04X4c3CgL6NPLUPrl64aV1N4w9Ug,46752
|
|
||||||
matplotlib/mpl-data/fonts/ttf/STIXSizFiveSymReg.ttf,sha256=wYuH1gYUpCuusqItRH5kf9p_s6mUD-9X3L5RvRtKSxs,13656
|
|
||||||
matplotlib/mpl-data/fonts/ttf/STIXSizFourSymBol.ttf,sha256=yNdvjUoSmsZCULmD7SVq9HabndG9P4dPhboL1JpAf0s,12228
|
|
||||||
matplotlib/mpl-data/fonts/ttf/STIXSizFourSymReg.ttf,sha256=-9xVMYL4_1rcO8FiCKrCfR4PaSmKtA42ddLGqwtei1w,15972
|
|
||||||
matplotlib/mpl-data/fonts/ttf/STIXSizOneSymBol.ttf,sha256=cYexyo8rZcdqMlpa9fNF5a2IoXLUTZuIvh0JD1Qp0i4,12556
|
|
||||||
matplotlib/mpl-data/fonts/ttf/STIXSizOneSymReg.ttf,sha256=0lbHzpndzJmO8S42mlkhsz5NbvJLQCaH5Mcc7QZRDzc,19760
|
|
||||||
matplotlib/mpl-data/fonts/ttf/STIXSizThreeSymBol.ttf,sha256=3eBc-VtYbhQU3BnxiypfO6eAzEu8BdDvtIJSFbkS2oY,12192
|
|
||||||
matplotlib/mpl-data/fonts/ttf/STIXSizThreeSymReg.ttf,sha256=XFSKCptbESM8uxHtUFSAV2cybwxhSjd8dWVByq6f3w0,15836
|
|
||||||
matplotlib/mpl-data/fonts/ttf/STIXSizTwoSymBol.ttf,sha256=MUCYHrA0ZqFiSE_PjIGlJZgMuv79aUgQqE7Dtu3kuo0,12116
|
|
||||||
matplotlib/mpl-data/fonts/ttf/STIXSizTwoSymReg.ttf,sha256=_sdxDuEwBDtADpu9CyIXQxV7sIqA2TZVBCUiUjq5UCk,15704
|
|
||||||
matplotlib/mpl-data/fonts/ttf/cmb10.ttf,sha256=B0SXtQxD6ldZcYFZH5iT04_BKofpUQT1ZX_CSB9hojo,25680
|
|
||||||
matplotlib/mpl-data/fonts/ttf/cmex10.ttf,sha256=ryjwwXByOsd2pxv6WVrKCemNFa5cPVTOGa_VYZyWqQU,21092
|
|
||||||
matplotlib/mpl-data/fonts/ttf/cmmi10.ttf,sha256=MJKWW4gR_WpnZXmWZIRRgfwd0TMLk3-RWAjEhdMWI00,32560
|
|
||||||
matplotlib/mpl-data/fonts/ttf/cmr10.ttf,sha256=Tdl2GwWMAJ25shRfVe5mF9CTwnPdPWxbPkP_YRD6m_Y,26348
|
|
||||||
matplotlib/mpl-data/fonts/ttf/cmss10.ttf,sha256=ffkag9BbLkcexjjLC0NaNgo8eSsJ_EKn2mfpHy55EVo,20376
|
|
||||||
matplotlib/mpl-data/fonts/ttf/cmsy10.ttf,sha256=uyJu2TLz8QDNDlL15JEu5VO0G2nnv9uNOFTbDrZgUjI,29396
|
|
||||||
matplotlib/mpl-data/fonts/ttf/cmtt10.ttf,sha256=YhHwmuk1mZka_alwwkZp2tGnfiU9kVYk-_IS9wLwcdc,28136
|
|
||||||
matplotlib/mpl-data/images/back.gif,sha256=sdkxFRAh-Mgs44DTvruO5OxcI3Av9CS1g5MqMA_DDkQ,608
|
|
||||||
matplotlib/mpl-data/images/back.pdf,sha256=ZR7CJo_dAeCM-KlaGvskgtHQyRtrPIolc8REOmcoqJk,1623
|
|
||||||
matplotlib/mpl-data/images/back.png,sha256=E4dGf4Gnz1xJ1v2tMygHV0YNQgShreDeVApaMb-74mU,380
|
|
||||||
matplotlib/mpl-data/images/back.svg,sha256=yRdMiKsa-awUm2x_JE_rEV20rNTa7FInbFBEoMo-6ik,1512
|
|
||||||
matplotlib/mpl-data/images/back_large.gif,sha256=tqCtecrxNrPuDCUj7FGs8UXWftljKcwgp5cSBBhXwiQ,799
|
|
||||||
matplotlib/mpl-data/images/back_large.png,sha256=9A6hUSQeszhYONE4ZuH3kvOItM0JfDVu6tkfromCbsQ,620
|
|
||||||
matplotlib/mpl-data/images/filesave.gif,sha256=wAyNwOPd9c-EIPwcUAlqHSfLmxq167nhDVppOWPy9UA,723
|
|
||||||
matplotlib/mpl-data/images/filesave.pdf,sha256=P1EPPV2g50WTt8UaX-6kFoTZM1xVqo6S2H6FJ6Zd1ec,1734
|
|
||||||
matplotlib/mpl-data/images/filesave.png,sha256=b7ctucrM_F2mG-DycTedG_a_y4pHkx3F-zM7l18GLhk,458
|
|
||||||
matplotlib/mpl-data/images/filesave.svg,sha256=oxPVbLS9Pzelz71C1GCJWB34DZ0sx_pUVPRHBrCZrGs,2029
|
|
||||||
matplotlib/mpl-data/images/filesave_large.gif,sha256=IXrenlwu3wwO8WTRvxHt_q62NF6ZWyqk3jZhm6GE-G8,1498
|
|
||||||
matplotlib/mpl-data/images/filesave_large.png,sha256=LNbRD5KZ3Kf7nbp-stx_a1_6XfGBSWUfDdpgmnzoRvk,720
|
|
||||||
matplotlib/mpl-data/images/forward.gif,sha256=VNL9R-dECOX7wUAYPtU_DWn5hwi3SwLR17DhmBvUIxE,590
|
|
||||||
matplotlib/mpl-data/images/forward.pdf,sha256=KIqIL4YId43LkcOxV_TT5uvz1SP8k5iUNUeJmAElMV8,1630
|
|
||||||
matplotlib/mpl-data/images/forward.png,sha256=pKbLepgGiGeyY2TCBl8svjvm7Z4CS3iysFxcq4GR-wk,357
|
|
||||||
matplotlib/mpl-data/images/forward.svg,sha256=NnQDOenfjsn-o0aJMUfErrP320Zcx9XHZkLh0cjMHsk,1531
|
|
||||||
matplotlib/mpl-data/images/forward_large.gif,sha256=H6Jbcc7qJwHJAE294YqI5Bm-5irofX40cKRvYdrG_Ig,786
|
|
||||||
matplotlib/mpl-data/images/forward_large.png,sha256=36h7m7DZDHql6kkdpNPckyi2LKCe_xhhyavWARz_2kQ,593
|
|
||||||
matplotlib/mpl-data/images/hand.gif,sha256=3lRfmAqQU7A2t1YXXsB9IbwzK7FaRh-IZO84D5-xCrw,1267
|
|
||||||
matplotlib/mpl-data/images/hand.pdf,sha256=hspwkNY915KPD7AMWnVQs7LFPOtlcj0VUiLu76dMabQ,4172
|
|
||||||
matplotlib/mpl-data/images/hand.png,sha256=2cchRETGKa0hYNKUxnJABwkyYXEBPqJy_VqSPlT0W2Q,979
|
|
||||||
matplotlib/mpl-data/images/hand.svg,sha256=tsVIES_nINrAbH4FqdsCGOx0SVE37vcofSYBhnnaOP0,4888
|
|
||||||
matplotlib/mpl-data/images/hand_large.gif,sha256=H5IHmVTvOqHQb9FZ_7g7AlPt9gv-zRq0L5_Q9B7OuvU,973
|
|
||||||
matplotlib/mpl-data/images/help.pdf,sha256=CeE978IMi0YWznWKjIT1R8IrP4KhZ0S7usPUvreSgcA,1813
|
|
||||||
matplotlib/mpl-data/images/help.png,sha256=s4pQrqaQ0py8I7vc9hv3BI3DO_tky-7YBMpaHuBDCBY,472
|
|
||||||
matplotlib/mpl-data/images/help.ppm,sha256=mVPvgwcddzCM-nGZd8Lnl_CorzDkRIXQE17b7qo8vlU,1741
|
|
||||||
matplotlib/mpl-data/images/help.svg,sha256=KXabvQhqIWen_t2SvZuddFYa3S0iI3W8cAKm3s1fI8Q,1870
|
|
||||||
matplotlib/mpl-data/images/help_large.png,sha256=1IwEyWfGRgnoCWM-r9CJHEogTJVD5n1c8LXTK4AJ4RE,747
|
|
||||||
matplotlib/mpl-data/images/help_large.ppm,sha256=MiCSKp1Su88FXOi9MTtkQDA2srwbX3w5navi6cneAi4,6925
|
|
||||||
matplotlib/mpl-data/images/home.gif,sha256=NKuFM7tTtFngdfsOpJ4AxYTL8PYS5GWKAoiJjBMwLlU,666
|
|
||||||
matplotlib/mpl-data/images/home.pdf,sha256=e0e0pI-XRtPmvUCW2VTKL1DeYu1pvPmUUeRSgEbWmik,1737
|
|
||||||
matplotlib/mpl-data/images/home.png,sha256=IcFdAAUa6_A0qt8IO3I8p4rpXpQgAlJ8ndBECCh7C1w,468
|
|
||||||
matplotlib/mpl-data/images/home.svg,sha256=n_AosjJVXET3McymFuHgXbUr5vMLdXK2PDgghX8Cch4,1891
|
|
||||||
matplotlib/mpl-data/images/home_large.gif,sha256=k86PJCgED46sCFkOlUYHA0s5U7OjRsc517bpAtU2JSw,1422
|
|
||||||
matplotlib/mpl-data/images/home_large.png,sha256=uxS2O3tWOHh1iau7CaVV4ermIJaZ007ibm5Z3i8kXYg,790
|
|
||||||
matplotlib/mpl-data/images/matplotlib.pdf,sha256=BkSUf-2xoij-eXfpV2t7y1JFKG1zD1gtV6aAg3Xi_wE,22852
|
|
||||||
matplotlib/mpl-data/images/matplotlib.png,sha256=w8KLRYVa-voUZXa41hgJauQuoois23f3NFfdc72pUYY,1283
|
|
||||||
matplotlib/mpl-data/images/matplotlib.svg,sha256=QiTIcqlQwGaVPtHsEk-vtmJk1wxwZSvijhqBe_b9VCI,62087
|
|
||||||
matplotlib/mpl-data/images/matplotlib_128.ppm,sha256=IHPRWXpLFRq3Vb7UjiCkFrN_N86lSPcfrEGunST08d8,49167
|
|
||||||
matplotlib/mpl-data/images/matplotlib_large.png,sha256=ElRoue9grUqkZXJngk-nvh4GKfpvJ4gE69WryjCbX5U,3088
|
|
||||||
matplotlib/mpl-data/images/move.gif,sha256=FN52MptH4FZiwmV2rQgYCO2FvO3m5LtqYv8jk6Xbeyk,679
|
|
||||||
matplotlib/mpl-data/images/move.pdf,sha256=CXk3PGK9WL5t-5J-G2X5Tl-nb6lcErTBS5oUj2St6aU,1867
|
|
||||||
matplotlib/mpl-data/images/move.png,sha256=TmjR41IzSzxGbhiUcV64X0zx2BjrxbWH3cSKvnG2vzc,481
|
|
||||||
matplotlib/mpl-data/images/move.svg,sha256=_ZKpcwGD6DMTkZlbyj0nQbT8Ygt5vslEZ0OqXaXGd4E,2509
|
|
||||||
matplotlib/mpl-data/images/move_large.gif,sha256=RMIAr-G9OOY7vWC04oN6qv5TAHJxhQGhLsw_bNsvWbg,951
|
|
||||||
matplotlib/mpl-data/images/move_large.png,sha256=Skjz2nW_RTA5s_0g88gdq2hrVbm6DOcfYW4Fu42Fn9U,767
|
|
||||||
matplotlib/mpl-data/images/qt4_editor_options.pdf,sha256=2qu6GVyBrJvVHxychQoJUiXPYxBylbH2j90QnytXs_w,1568
|
|
||||||
matplotlib/mpl-data/images/qt4_editor_options.png,sha256=EryQjQ5hh2dwmIxtzCFiMN1U6Tnd11p1CDfgH5ZHjNM,380
|
|
||||||
matplotlib/mpl-data/images/qt4_editor_options.svg,sha256=E00YoX7u4NrxMHm_L1TM8PDJ88bX5qRdCrO-Uj59CEA,1244
|
|
||||||
matplotlib/mpl-data/images/qt4_editor_options_large.png,sha256=-Pd-9Vh5aIr3PZa8O6Ge_BLo41kiEnpmkdDj8a11JkY,619
|
|
||||||
matplotlib/mpl-data/images/subplots.gif,sha256=QfhmUdcrko08-WtrzCJUjrVFDTvUZCJEXpARNtzEwkg,691
|
|
||||||
matplotlib/mpl-data/images/subplots.pdf,sha256=Q0syPMI5EvtgM-CE-YXKOkL9eFUAZnj_X2Ihoj6R4p4,1714
|
|
||||||
matplotlib/mpl-data/images/subplots.png,sha256=MUfCItq3_yzb9yRieGOglpn0Y74h8IA7m5i70B63iRc,445
|
|
||||||
matplotlib/mpl-data/images/subplots.svg,sha256=8acBogXIr9OWGn1iD6mUkgahdFZgDybww385zLCLoIs,2130
|
|
||||||
matplotlib/mpl-data/images/subplots_large.gif,sha256=Ff3ERmtVAaGP9i1QGUNnIIKac6LGuSW2Qf4DrockZSI,1350
|
|
||||||
matplotlib/mpl-data/images/subplots_large.png,sha256=Edu9SwVMQEXJZ5ogU5cyW7VLcwXJdhdf-EtxxmxdkIs,662
|
|
||||||
matplotlib/mpl-data/images/zoom_to_rect.gif,sha256=mTX6h9fh2W9zmvUYqeibK0TZ7qIMKOB1nAXMpD_jDys,696
|
|
||||||
matplotlib/mpl-data/images/zoom_to_rect.pdf,sha256=SEvPc24gfZRpl-dHv7nx8KkxPyU66Kq4zgQTvGFm9KA,1609
|
|
||||||
matplotlib/mpl-data/images/zoom_to_rect.png,sha256=aNz3QZBrIgxu9E-fFfaQweCVNitGuDUFoC27e5NU2L4,530
|
|
||||||
matplotlib/mpl-data/images/zoom_to_rect.svg,sha256=1vRxr3cl8QTwTuRlQzD1jxu0fXZofTJ2PMgG97E7Bco,1479
|
|
||||||
matplotlib/mpl-data/images/zoom_to_rect_large.gif,sha256=nx5LUpTAH6ZynM3ZfZDS-wR87jbMUsUnyQ27NGkV0_c,1456
|
|
||||||
matplotlib/mpl-data/images/zoom_to_rect_large.png,sha256=V6pkxmm6VwFExdg_PEJWdK37HB7k3cE_corLa7RbUMk,1016
|
|
||||||
matplotlib/mpl-data/matplotlibrc,sha256=ZDuS3NjqmSy4_oIXNk9mMNcD74ExJ9clpz6fbgSVMCk,40282
|
|
||||||
matplotlib/mpl-data/sample_data/Minduka_Present_Blue_Pack.png,sha256=XnKGiCanpDKalQ5anvo5NZSAeDP7fyflzQAaivuc0IE,13634
|
|
||||||
matplotlib/mpl-data/sample_data/None_vs_nearest-pdf.png,sha256=5CPvcG3SDNfOXx39CMKHCNS9JKZ-fmOUwIfpppNXsQ0,106228
|
|
||||||
matplotlib/mpl-data/sample_data/README.txt,sha256=ABz19VBKfGewdY39QInG9Qccgn1MTYV3bT5Ph7TCy2Y,128
|
|
||||||
matplotlib/mpl-data/sample_data/aapl.npz,sha256=GssVYka_EccteiXbNRJJ5GsuqU7G8F597qX7srYXZsw,107503
|
|
||||||
matplotlib/mpl-data/sample_data/ada.png,sha256=X1hjJK1_1Nc8DN-EEhey3G7Sq8jBwQDKNSl4cCAE0uY,308313
|
|
||||||
matplotlib/mpl-data/sample_data/axes_grid/bivariate_normal.npy,sha256=DpWZ9udAh6ospYqneEa27D6EkRgORFwHosacZXVu98U,1880
|
|
||||||
matplotlib/mpl-data/sample_data/ct.raw.gz,sha256=LDvvgH-mycRQF2D29-w5MW94ZI0opvwKUoFI8euNpMk,256159
|
|
||||||
matplotlib/mpl-data/sample_data/data_x_x2_x3.csv,sha256=A0SU3buOUGhT-NI_6LQ6p70fFSIU3iLFdgzvzrKR6SE,132
|
|
||||||
matplotlib/mpl-data/sample_data/demodata.csv,sha256=MRybziqnyrqMCH9qG7Mr6BwcohIhftVG5dejXV2AX2M,659
|
|
||||||
matplotlib/mpl-data/sample_data/eeg.dat,sha256=KGVjFt8ABKz7p6XZirNfcxSTOpGGNuyA8JYErRKLRBc,25600
|
|
||||||
matplotlib/mpl-data/sample_data/embedding_in_wx3.xrc,sha256=cUqVw5vDHNSZoaO4J0ebZUf5SrJP36775abs7R9Bclg,2186
|
|
||||||
matplotlib/mpl-data/sample_data/goog.npz,sha256=QAkXzzDmtmT3sNqT18dFhg06qQCNqLfxYNLdEuajGLE,22845
|
|
||||||
matplotlib/mpl-data/sample_data/grace_hopper.jpg,sha256=qMptc0dlcDsJcoq0f-WfRz2Trjln_CTHwCiMPHrbcTA,61306
|
|
||||||
matplotlib/mpl-data/sample_data/grace_hopper.png,sha256=MCf0ju2kpC40srQ0xw4HEyOoKhLL4khP3jHfU9_dR7s,628280
|
|
||||||
matplotlib/mpl-data/sample_data/jacksboro_fault_dem.npz,sha256=1JP1CjPoKkQgSUxU0fyhU50Xe9wnqxkLxf5ukvYvtjc,174061
|
|
||||||
matplotlib/mpl-data/sample_data/logo2.png,sha256=ITxkJUsan2oqXgJDy6DJvwJ4aHviKeWGnxPkTjXUt7A,33541
|
|
||||||
matplotlib/mpl-data/sample_data/membrane.dat,sha256=q3lbQpIBpbtXXGNw1eFwkN_PwxdDGqk4L46IE2b0M1c,48000
|
|
||||||
matplotlib/mpl-data/sample_data/msft.csv,sha256=GArKb0O3DgKZRsKdJf6lX3rMSf-PCekIiBoLNdgF7Mk,3211
|
|
||||||
matplotlib/mpl-data/sample_data/percent_bachelors_degrees_women_usa.csv,sha256=TzoqamsV_N3d3lW7SKmj14zZVX4FOOg9jJcsC5U9pbA,5681
|
|
||||||
matplotlib/mpl-data/sample_data/s1045.ima.gz,sha256=MrQk1k9it-ccsk0p_VOTitVmTWCAVaZ6srKvQ2n4uJ4,33229
|
|
||||||
matplotlib/mpl-data/sample_data/topobathy.npz,sha256=AkTgMpFwLfRQJNy1ysvE89TLMNct-n_TccSsYcQrT78,45224
|
|
||||||
matplotlib/mpl-data/stylelib/Solarize_Light2.mplstyle,sha256=PECeO60wwJe2sSDvxapBJRuKGek0qLcoaN8qOX6tgNQ,1255
|
|
||||||
matplotlib/mpl-data/stylelib/_classic_test_patch.mplstyle,sha256=iopHpMaM3im_AK2aiHGuM2DKM5i9Kc84v6NQEoSb10Q,167
|
|
||||||
matplotlib/mpl-data/stylelib/bmh.mplstyle,sha256=-KbhaI859BITHIoyUZIfpQDjfckgLAlDAS_ydKsm6mc,712
|
|
||||||
matplotlib/mpl-data/stylelib/classic.mplstyle,sha256=0RjtrDi0vZOzWGnt9cme_At_9GqMwHzwEBCAH9OQZ7I,24511
|
|
||||||
matplotlib/mpl-data/stylelib/dark_background.mplstyle,sha256=-EGmoFm_35Zk7oRp29UalT56HsOSuJbYMeQGdAATnz4,477
|
|
||||||
matplotlib/mpl-data/stylelib/fast.mplstyle,sha256=yTa2YEIIP9xi5V_G0p2vSlxghuhNwjRi9gPECMxyRiM,288
|
|
||||||
matplotlib/mpl-data/stylelib/fivethirtyeight.mplstyle,sha256=WNUmAFuBPcqQPVgt6AS1ldy8Be2XO01N-1YQL__Q6ZY,832
|
|
||||||
matplotlib/mpl-data/stylelib/ggplot.mplstyle,sha256=xhjLwr8hiikEXKy8APMy0Bmvtz1g0WnG84gX7e9lArs,957
|
|
||||||
matplotlib/mpl-data/stylelib/grayscale.mplstyle,sha256=KCLg-pXpns9cnKDXKN2WH6mV41OH-6cbT-5zKQotSdw,526
|
|
||||||
matplotlib/mpl-data/stylelib/seaborn-bright.mplstyle,sha256=pDqn3-NUyVLvlfkYs8n8HzNZvmslVMChkeH-HtZuJIc,144
|
|
||||||
matplotlib/mpl-data/stylelib/seaborn-colorblind.mplstyle,sha256=eCSzFj5_2vR6n5qu1rHE46wvSVGZcdVqz85ov40ZsH8,148
|
|
||||||
matplotlib/mpl-data/stylelib/seaborn-dark-palette.mplstyle,sha256=p5ABKNQHRG7bk4HXqMQrRBjDlxGAo3RCXHdQmP7g-Ng,142
|
|
||||||
matplotlib/mpl-data/stylelib/seaborn-dark.mplstyle,sha256=I4xQ75vE5_9X4k0cNDiqhhnF3OcrZ2xlPX8Ll7OCkoE,667
|
|
||||||
matplotlib/mpl-data/stylelib/seaborn-darkgrid.mplstyle,sha256=2bXOSzS5gmPzRBrRmzVWyhg_7ZaBRQ6t_-O-cRuyZoA,670
|
|
||||||
matplotlib/mpl-data/stylelib/seaborn-deep.mplstyle,sha256=44dLcXjjRgR-6yaopgGRInaVgz3jk8VJVQTbBIcxRB0,142
|
|
||||||
matplotlib/mpl-data/stylelib/seaborn-muted.mplstyle,sha256=T4o3jvqKD_ImXDkp66XFOV_xrBVFUolJU34JDFk1Xkk,143
|
|
||||||
matplotlib/mpl-data/stylelib/seaborn-notebook.mplstyle,sha256=PcvZQbYrDdducrNlavBPmQ1g2minio_9GkUUFRdgtoM,382
|
|
||||||
matplotlib/mpl-data/stylelib/seaborn-paper.mplstyle,sha256=n0mboUp2C4Usq2j6tNWcu4TZ_YT4-kKgrYO0t-rz1yw,393
|
|
||||||
matplotlib/mpl-data/stylelib/seaborn-pastel.mplstyle,sha256=8nV8qRpbUrnFZeyE6VcQ1oRuZPLil2W74M2U37DNMOE,144
|
|
||||||
matplotlib/mpl-data/stylelib/seaborn-poster.mplstyle,sha256=dUaKqTE4MRfUq2rWVXbbou7kzD7Z9PE9Ko8aXLza8JA,403
|
|
||||||
matplotlib/mpl-data/stylelib/seaborn-talk.mplstyle,sha256=7FnBaBEdWBbncTm6_ER-EQVa_bZgU7dncgez-ez8R74,403
|
|
||||||
matplotlib/mpl-data/stylelib/seaborn-ticks.mplstyle,sha256=CITZmZFUFp40MK2Oz8tI8a7WRoCizQU9Z4J172YWfWw,665
|
|
||||||
matplotlib/mpl-data/stylelib/seaborn-white.mplstyle,sha256=WjJ6LEU6rlCwUugToawciAbKP9oERFHr9rfFlUrdTx0,665
|
|
||||||
matplotlib/mpl-data/stylelib/seaborn-whitegrid.mplstyle,sha256=ec4BjsNzmOvHptcJ3mdPxULF3S1_U1EUocuqfIpw-Nk,664
|
|
||||||
matplotlib/mpl-data/stylelib/seaborn.mplstyle,sha256=_Xu6qXKzi4b3GymCOB1b1-ykKTQ8xhDliZ8ezHGTiAs,1130
|
|
||||||
matplotlib/mpl-data/stylelib/tableau-colorblind10.mplstyle,sha256=BsirZVd1LmPWT4tBIz6loZPjZcInoQrIGfC7rvzqmJw,190
|
|
||||||
matplotlib/offsetbox.py,sha256=1oReQSHV50aRsHqHIa3Km234FXx8sUZRLdiGbdGu2zU,58812
|
|
||||||
matplotlib/patches.py,sha256=4JTt8OKfTg_BzSQVXYjsQLAFbZvvzR9T-1zsajaPpx8,151886
|
|
||||||
matplotlib/path.py,sha256=ov2ghbmWhCV-PhxUPGEfsG409Nrkf9HP4u7oQSpGFtc,37640
|
|
||||||
matplotlib/patheffects.py,sha256=ERzaWP5RZTnaEVWx77c8oB-JQeMpVJtY-hBdRqkQ4ZM,13235
|
|
||||||
matplotlib/projections/__init__.py,sha256=4b447LtxkDz1nC1B9tb_J7cCpq1fjxwaEvzkHy-Y3KA,1816
|
|
||||||
matplotlib/projections/__pycache__/__init__.cpython-37.pyc,,
|
|
||||||
matplotlib/projections/__pycache__/geo.cpython-37.pyc,,
|
|
||||||
matplotlib/projections/__pycache__/polar.cpython-37.pyc,,
|
|
||||||
matplotlib/projections/geo.py,sha256=OrTW_dk4QqrTv9lYBean9uz24MBIWyWcnkADyTOdNuc,17690
|
|
||||||
matplotlib/projections/polar.py,sha256=1aHOdhpaJKpu5BNS2eRoeIgej-QUunRpIGcxXkv1s28,52508
|
|
||||||
matplotlib/pylab.py,sha256=VOs5onux2-yPGn0exAPsR75U9ty2hOzvg8Nz1K7TWBg,9595
|
|
||||||
matplotlib/pyplot.py,sha256=vM3sVw0yIb0EbehwlLAOWHfGnMSN4W9OfTDmcsBELvs,111042
|
|
||||||
matplotlib/quiver.py,sha256=B3CGGxSNVLwOPx2IgyG2DCSPQHs1MAS0o9sL_4Mm7rY,48018
|
|
||||||
matplotlib/rcsetup.py,sha256=BhPaDqHrifbncC47epnKBtvlkk-MzhNp1HlVYgcgvF8,58589
|
|
||||||
matplotlib/sankey.py,sha256=3PygeZ3h19RFICw1hL6qt5TwRoBrP1AKSznWvKHc6Z4,36986
|
|
||||||
matplotlib/scale.py,sha256=_G5Aq3ta2vc2WOLuL3_UlnZ8XsXbGRrwBuqAG_OxCxU,25209
|
|
||||||
matplotlib/sphinxext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
||||||
matplotlib/sphinxext/__pycache__/__init__.cpython-37.pyc,,
|
|
||||||
matplotlib/sphinxext/__pycache__/mathmpl.cpython-37.pyc,,
|
|
||||||
matplotlib/sphinxext/__pycache__/plot_directive.cpython-37.pyc,,
|
|
||||||
matplotlib/sphinxext/mathmpl.py,sha256=jTqwBfxLLGjx-4TwEzwYvi2WdCoJpqHfDcbLKrgcKss,4276
|
|
||||||
matplotlib/sphinxext/plot_directive.py,sha256=dAECzhJ1qVCq3nN3poGjKK2AAaAIwGikEHQIz_V0U0Y,26574
|
|
||||||
matplotlib/spines.py,sha256=Xl9hIsBHzYaGq79UQb3Amfwfrq1-ZNsiS4wpPwstbp8,21227
|
|
||||||
matplotlib/stackplot.py,sha256=fj4oqFbYA1G3RaTnV_Jic5mn5K3rza-JYp6jGR7e0yk,3917
|
|
||||||
matplotlib/streamplot.py,sha256=9zniqozPg42NfXk4bx_Ro2RlkYYuR2CEJwJfJkt7jtI,22641
|
|
||||||
matplotlib/style/__init__.py,sha256=EExOAUAq3u_rscUwkfKtZoEgLA5npmltCrYZOP9ftjw,67
|
|
||||||
matplotlib/style/__pycache__/__init__.cpython-37.pyc,,
|
|
||||||
matplotlib/style/__pycache__/core.cpython-37.pyc,,
|
|
||||||
matplotlib/style/core.py,sha256=EAubJQ90H__1bljwNfjpT8kxHp30r6KtXoveLvnfs4Q,8222
|
|
||||||
matplotlib/table.py,sha256=FXhhFOy_-ZkHwyphkjFBQku1WgDjR3iYlmV4Wvls0cY,26674
|
|
||||||
matplotlib/testing/__init__.py,sha256=MVV0ao_RHOKgDhpSN7QJBnyunje7tDeco-No_HtvvcQ,1428
|
|
||||||
matplotlib/testing/__pycache__/__init__.cpython-37.pyc,,
|
|
||||||
matplotlib/testing/__pycache__/compare.cpython-37.pyc,,
|
|
||||||
matplotlib/testing/__pycache__/conftest.cpython-37.pyc,,
|
|
||||||
matplotlib/testing/__pycache__/decorators.cpython-37.pyc,,
|
|
||||||
matplotlib/testing/__pycache__/disable_internet.cpython-37.pyc,,
|
|
||||||
matplotlib/testing/__pycache__/exceptions.cpython-37.pyc,,
|
|
||||||
matplotlib/testing/compare.py,sha256=67rAW447H4AUnGoT-AUP7s6CB2Q1N4oqhetFdvBdKZk,16969
|
|
||||||
matplotlib/testing/conftest.py,sha256=juolFb13qZ_jwO6DsOxkfCKuPmPsQwbY6Oznx76tLYo,4317
|
|
||||||
matplotlib/testing/decorators.py,sha256=t9XYPto5sIm4OObU5dyF6z5FjdhuNE2saBr-dnZ45wU,17704
|
|
||||||
matplotlib/testing/disable_internet.py,sha256=ovCho7Nu6w-uoJeUPjJS7XGKJN0ktSNyF6NODaEyjb4,4925
|
|
||||||
matplotlib/testing/exceptions.py,sha256=72QmjiHG7DwxSvlJf8mei-hRit5AH3NKh0-osBo4YbY,138
|
|
||||||
matplotlib/testing/jpl_units/Duration.py,sha256=Leomw6a4XHddFgqMoYj63HfxV_-u6_MuQ3iaQ26TJcg,4946
|
|
||||||
matplotlib/testing/jpl_units/Epoch.py,sha256=XpQMTIOs6VIVzuFYxRcv6JUuz4kqVCb1nGfBpYYbeJA,6305
|
|
||||||
matplotlib/testing/jpl_units/EpochConverter.py,sha256=TAhtAyDHvvxDJL036DWEXrkZl_CwpVl2y5FNXloAoxo,4067
|
|
||||||
matplotlib/testing/jpl_units/StrConverter.py,sha256=36hFTYbCM3Dh9_QR82dBbHh_7DSpsEthpnJYRICLlIc,4107
|
|
||||||
matplotlib/testing/jpl_units/UnitDbl.py,sha256=sL0U984sJmka_0gzp6uhxSJuxnuh77aDAjtfCYdYJZ0,7793
|
|
||||||
matplotlib/testing/jpl_units/UnitDblConverter.py,sha256=M5h3lOB4IEysqnR7VbkjUnMPS7wBtrZYWKvU3JUaJtI,4145
|
|
||||||
matplotlib/testing/jpl_units/UnitDblFormatter.py,sha256=CRcbPtE3K0FlFJ4hkhi-SgQl1MUV-VlmIeOPIEPNwuI,681
|
|
||||||
matplotlib/testing/jpl_units/__init__.py,sha256=Bp4Lz_eqRuxNWO_l3VvhuurFZaUmZIlvcF3N0UBmzHc,2692
|
|
||||||
matplotlib/testing/jpl_units/__pycache__/Duration.cpython-37.pyc,,
|
|
||||||
matplotlib/testing/jpl_units/__pycache__/Epoch.cpython-37.pyc,,
|
|
||||||
matplotlib/testing/jpl_units/__pycache__/EpochConverter.cpython-37.pyc,,
|
|
||||||
matplotlib/testing/jpl_units/__pycache__/StrConverter.cpython-37.pyc,,
|
|
||||||
matplotlib/testing/jpl_units/__pycache__/UnitDbl.cpython-37.pyc,,
|
|
||||||
matplotlib/testing/jpl_units/__pycache__/UnitDblConverter.cpython-37.pyc,,
|
|
||||||
matplotlib/testing/jpl_units/__pycache__/UnitDblFormatter.cpython-37.pyc,,
|
|
||||||
matplotlib/testing/jpl_units/__pycache__/__init__.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__init__.py,sha256=ns6SIKdszYNXD5h5PqKRCR06Z45H-sXrUX2VwujSRIM,366
|
|
||||||
matplotlib/tests/__pycache__/__init__.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/conftest.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_afm.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_agg.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_agg_filter.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_animation.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_arrow_patches.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_artist.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_axes.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_backend_bases.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_backend_cairo.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_backend_nbagg.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_backend_pdf.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_backend_pgf.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_backend_ps.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_backend_qt.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_backend_svg.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_backend_tk.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_backend_tools.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_backend_webagg.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_backends_interactive.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_basic.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_bbox_tight.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_category.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_cbook.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_collections.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_colorbar.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_colors.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_compare_images.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_constrainedlayout.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_container.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_contour.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_cycles.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_dates.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_determinism.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_dviread.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_figure.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_font_manager.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_fontconfig_pattern.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_gridspec.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_image.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_legend.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_lines.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_marker.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_mathtext.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_matplotlib.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_mlab.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_offsetbox.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_patches.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_path.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_patheffects.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_pickle.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_png.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_preprocess_data.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_pyplot.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_quiver.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_rcparams.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_sankey.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_scale.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_simplification.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_skew.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_sphinxext.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_spines.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_streamplot.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_style.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_subplots.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_table.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_testing.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_texmanager.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_text.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_ticker.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_tightlayout.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_transforms.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_triangulation.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_ttconv.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_type1font.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_units.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_usetex.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/__pycache__/test_widgets.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/cmr10.pfb,sha256=_c7eh5QBjfXytY8JBfsgorQY7Y9ntz7hJEWFXfvlsb4,35752
|
|
||||||
matplotlib/tests/conftest.py,sha256=QtpdWPUoXL_9F8WIytDc3--h0nPjbo8PToig7svIT1Y,258
|
|
||||||
matplotlib/tests/mpltest.ttf,sha256=Jwb2O5KRVk_2CMqnhL0igeI3iGQCY3eChyS16N589zE,2264
|
|
||||||
matplotlib/tests/test_afm.py,sha256=DGVfvABg6FRmbAq2ldRhM2wlqNfVrmRtSz12MCyqDXk,3710
|
|
||||||
matplotlib/tests/test_agg.py,sha256=SC6WsFbq9Hs4dokpEqGqGPaFGS7zJpNxKRIRLUzD3Qk,7558
|
|
||||||
matplotlib/tests/test_agg_filter.py,sha256=sfntvGVUuCaGqU3DdOnTRXqq0P1afVqWuaV_ZEYh8kQ,969
|
|
||||||
matplotlib/tests/test_animation.py,sha256=WZ2kU7tjlDXL5Ryf89irQok884cWGtkVOJpNSjVyj3o,8916
|
|
||||||
matplotlib/tests/test_arrow_patches.py,sha256=3EB9HIfdLCg_Nvq8zxEH9LJAV5OUbo6yndbZ-lIVcnQ,5593
|
|
||||||
matplotlib/tests/test_artist.py,sha256=hMSfbg8Le0Li-vLEk2N9tZQtC1cUUE5Xn0O4CgYLugs,9418
|
|
||||||
matplotlib/tests/test_axes.py,sha256=nRp8gbewUffIIfUBFlBxkq5E6FnH75wrCFY4Xp4GpG8,216153
|
|
||||||
matplotlib/tests/test_backend_bases.py,sha256=I3Oiqk6Fm-fctj-aOxq5Av8Kqe3QLjlY-oTwTbdO6dw,3811
|
|
||||||
matplotlib/tests/test_backend_cairo.py,sha256=gIjbQesBuvIBdpzoXXSdRmq3E2axCVX4h1Qfv6PNeKM,1936
|
|
||||||
matplotlib/tests/test_backend_nbagg.py,sha256=dp9pYxWXN8ZBBjJcVE-1tJ61K7oeWtzcqIsAd7ABnfk,948
|
|
||||||
matplotlib/tests/test_backend_pdf.py,sha256=GUqvImL8-HgpZGG0Zb41AE3KqVwtt8i00xcPutzGM1w,6696
|
|
||||||
matplotlib/tests/test_backend_pgf.py,sha256=GAArsyhcLvWIHDtKgdv2kscRlgpNQ_oqyOXVGdVTw3Q,8636
|
|
||||||
matplotlib/tests/test_backend_ps.py,sha256=E3eheQhOHcUhub4IzcWcDVvvnnVC6bHn6tv1NAF_KA4,3633
|
|
||||||
matplotlib/tests/test_backend_qt.py,sha256=Oqtl2ZuS8Ly_ouDGkwndSheCs8U9OSiwBwJnnMmVGXI,9798
|
|
||||||
matplotlib/tests/test_backend_svg.py,sha256=rPppxppM-G4mm4ISP4hq7pIVGTfS6Zyydt1jUoY2QqY,5863
|
|
||||||
matplotlib/tests/test_backend_tk.py,sha256=sLqemf0mAFMIpv2414wKSVInLekL8bvzzaeREhE2UBU,934
|
|
||||||
matplotlib/tests/test_backend_tools.py,sha256=C-B7NCkyWsQ5KzQEnI5Be16DsAHHZJU9P5v9--wsF-o,501
|
|
||||||
matplotlib/tests/test_backend_webagg.py,sha256=u-UvO04iqxZbFlUrNIfyD0KIAxEhSOyqlrOqxO4DnDw,702
|
|
||||||
matplotlib/tests/test_backends_interactive.py,sha256=QsdZhWATJPh3ZYM2F90MRQCyoW3ROUOGXYgrM0XUxsc,5018
|
|
||||||
matplotlib/tests/test_basic.py,sha256=KRMwLx3J53urIx689lWHzkWkaWGTf0ZwhTyGrFDUfao,1268
|
|
||||||
matplotlib/tests/test_bbox_tight.py,sha256=3nrCNbVtd-0K3LvndlPQBG9raTLdbXuDmoMWt5oVMSY,3902
|
|
||||||
matplotlib/tests/test_category.py,sha256=SKBDW4R4q_7A0K1H-q801mTivxBgcLXigw4E6-tb1P4,10011
|
|
||||||
matplotlib/tests/test_cbook.py,sha256=Z2Hp8UkeebK-BglQXm9WhiTpZC8CbSsSKUNy6hJoJbU,18684
|
|
||||||
matplotlib/tests/test_collections.py,sha256=9Lyyydi1Ykk0BKXXWDPSYUQ1M9F-uJdVwqaZE1ZMKxI,23520
|
|
||||||
matplotlib/tests/test_colorbar.py,sha256=OW2F_D6Vs7jEV8HOBh2kv_iV21u7sdyIqJcRakwEkTg,22065
|
|
||||||
matplotlib/tests/test_colors.py,sha256=KYXZa1yFlkEGriaLMm-v2WnhROS2lvOUgseSHV2xC7w,33376
|
|
||||||
matplotlib/tests/test_compare_images.py,sha256=n3Uoukid0GcjyQpd6ZrqIY9u3RLNE2XAPWwtcHIsqto,3155
|
|
||||||
matplotlib/tests/test_constrainedlayout.py,sha256=9689kXb21xPGT3rqgZMxVT8HT4HXlzjO_aS6wq7b8kM,12981
|
|
||||||
matplotlib/tests/test_container.py,sha256=75Di6cic-JY7JbOnsaz7N6Hcm3KUAJKaKbCoVSDPAuU,576
|
|
||||||
matplotlib/tests/test_contour.py,sha256=G4dN6t8yrbpKp0aEI1VTrb-woyBKidGUqdDJ3b5D55U,12018
|
|
||||||
matplotlib/tests/test_cycles.py,sha256=mgYXt63ov7th7IwGpLEoCh-ImubEp6wltzTbDchfQYI,7112
|
|
||||||
matplotlib/tests/test_dates.py,sha256=1oDBr8xj2v_5tLHP_1rMkKA2nikoXSxK5u44ekL_NLA,32805
|
|
||||||
matplotlib/tests/test_determinism.py,sha256=bu8E_NMdeN0X2KRMStjAgK3tklL5SG_IqYu4hov6Z-4,4586
|
|
||||||
matplotlib/tests/test_dviread.py,sha256=kTk9Qv6q9Kk3fJcDAEWm35HF-sKsP6Ybec6N8jEHasE,2342
|
|
||||||
matplotlib/tests/test_figure.py,sha256=EKv9PCtr5KU30dZ_tBjxfgrQryxYjf1u0YIS83mFfe8,15244
|
|
||||||
matplotlib/tests/test_font_manager.py,sha256=OrOm9CD4FnUnSzoQEpRNcsDktw7gNBz3h7YMPGkudjI,7217
|
|
||||||
matplotlib/tests/test_fontconfig_pattern.py,sha256=1MhBrF914MKxjbpdxKDqkfVyCZGnFBA06D2I6rqHRHo,2012
|
|
||||||
matplotlib/tests/test_gridspec.py,sha256=zahj5Rd4pB0xtAc_3KX7fQWyBys0P-IQk-Cq0cs8VgY,626
|
|
||||||
matplotlib/tests/test_image.py,sha256=RMReqvIC2celG9NhUkJzv7Cl2us5Pc3f8I4uhxAzGQs,36254
|
|
||||||
matplotlib/tests/test_legend.py,sha256=oXMRtvzQgYMqNC0vPR8mhqQQl5n-IZRBSIZbr_N4hVk,20051
|
|
||||||
matplotlib/tests/test_lines.py,sha256=zbpM3DO0F-aclKrTE2JliUZpBR1UV5coR6I5OXOvJbg,5970
|
|
||||||
matplotlib/tests/test_marker.py,sha256=yGEoHoMji04-BPN-mmddO60pcpGwvL6FMO101xz70dg,4768
|
|
||||||
matplotlib/tests/test_mathtext.py,sha256=xqmDclBoB-7253xFBgf_yI9JxdkYZfuYgJ66HFcyqQA,13331
|
|
||||||
matplotlib/tests/test_matplotlib.py,sha256=DIBqISzUIYanSxNWJL9n2oob1dRLOOAr6TIz2BTWK1I,706
|
|
||||||
matplotlib/tests/test_mlab.py,sha256=ZpoL_7s2ARzt3uhq1InSVEWahB-svI0siIutKqyyUpM,89334
|
|
||||||
matplotlib/tests/test_offsetbox.py,sha256=f_I8sNuPmN4TXQAKGp5w3XQvnpWVSrHgEZr_0ZR7siE,6633
|
|
||||||
matplotlib/tests/test_patches.py,sha256=NaNojcVYpt6Lw3xr4bcI1c6Tc0fjBlz5OkQMhZlLApg,16948
|
|
||||||
matplotlib/tests/test_path.py,sha256=X6kEMiXLHVdRaZ9w2JF2ID2_DtIVonQDByvXpLbKXSo,12736
|
|
||||||
matplotlib/tests/test_patheffects.py,sha256=I1C81Cms_QBK6cPg_xxKZBXKykZuGI5H2wwFtwnALZk,5207
|
|
||||||
matplotlib/tests/test_pickle.py,sha256=BahI72bPhtSEylUvRwKgksK4N5i2vjsQ1APvEw3Om-0,5653
|
|
||||||
matplotlib/tests/test_png.py,sha256=-ik0JJOAuZCED13VshP5RZsBOQpXu_Kv9I1oaZ_grxs,1705
|
|
||||||
matplotlib/tests/test_preprocess_data.py,sha256=vVnEzVU-jd1hAQwh-b9IbWo-S_pIg4I9NCpSQ1lLChI,10034
|
|
||||||
matplotlib/tests/test_pyplot.py,sha256=9KEPaGTyHduk7vi40kbva03HFk7bm8KrGlWjkBGMoQ0,1662
|
|
||||||
matplotlib/tests/test_quiver.py,sha256=_dGa3bJmvNqcnBvFhGntvhBKRipROZUNOrSm-lMtc7Y,8087
|
|
||||||
matplotlib/tests/test_rcparams.py,sha256=HnXA81intnBhogrXbCuaAfOV2nyvbGvOCESYElue6C4,20896
|
|
||||||
matplotlib/tests/test_sankey.py,sha256=KdWhgZpEiCJ8o7yuFjnCgqFeodwKSCuuhV_mhIc04dM,310
|
|
||||||
matplotlib/tests/test_scale.py,sha256=kolkvXNDsSm7P44yrVDNuz25lve4iGGreaG-JC8-VIA,5895
|
|
||||||
matplotlib/tests/test_simplification.py,sha256=_dIImjiA0VHBEbOrGQluQKCS6SQFwEVvfL9pqIn_SHI,11048
|
|
||||||
matplotlib/tests/test_skew.py,sha256=hngaWfqV6zqZSnRmVadBvtMIrg1snTZvu3fsqv5YddU,6310
|
|
||||||
matplotlib/tests/test_sphinxext.py,sha256=VfFfCq5T3jaVN0Ut67SHpilUOzl-_zaJDnGxfGEtrgA,2022
|
|
||||||
matplotlib/tests/test_spines.py,sha256=5jGy42khH7ndaHRCgJONXBOvM5ZnrzOhPSR42IAUAA0,3132
|
|
||||||
matplotlib/tests/test_streamplot.py,sha256=_9iDNwQ0M1djl0eEX94QJtPYqCKFN5ncU_cIKJlm39w,3909
|
|
||||||
matplotlib/tests/test_style.py,sha256=FKsTSWx43sls_PqZzOEJ-ZRaiBmSmVQCgCxfGTlyiNc,5677
|
|
||||||
matplotlib/tests/test_subplots.py,sha256=RIk5cOGJmZwQz4UzZ_IEe1rzx4riAjO3bdltY5p1F6k,5992
|
|
||||||
matplotlib/tests/test_table.py,sha256=UEvwlff7Jdx7ezPMc8nAdaCO0u11PzNpCZqYGLDS3O4,5685
|
|
||||||
matplotlib/tests/test_testing.py,sha256=6pJ-SCQP1Bj4Qw5m5CEz2aWV4Bl7ovXE2uUpttiIu3Y,449
|
|
||||||
matplotlib/tests/test_texmanager.py,sha256=zCtJ3JnZNfP2AQNy7q2LQAgaflSe7S5htJkJNylQSGE,459
|
|
||||||
matplotlib/tests/test_text.py,sha256=49TKkDPy_tFRyxPLSp8-GgeS8TdU87JW24IUvA13NVM,20461
|
|
||||||
matplotlib/tests/test_ticker.py,sha256=niDdQLrvTIUa4x0jWchca_LJJFQc7EQVfBopnF-DjEM,49453
|
|
||||||
matplotlib/tests/test_tightlayout.py,sha256=Rg-Vw7VJSFxonhO5qnb2StPkMK7R4jpohMdFQbtPVSc,9685
|
|
||||||
matplotlib/tests/test_transforms.py,sha256=1CO_STcfUU4yo4bJZLdTpJ7dF3E285LVbG-OBpFUchA,24892
|
|
||||||
matplotlib/tests/test_triangulation.py,sha256=KWSRvg-_xE5Wz-_LAqB-EvI_5uy9isc9GTmhmi189Kw,45372
|
|
||||||
matplotlib/tests/test_ttconv.py,sha256=w6U4-5OiEuXsOskvMz4E-f9iqPoxCt8dIC2TNB7PwXo,655
|
|
||||||
matplotlib/tests/test_type1font.py,sha256=C0pCPBGOv49SR2xxDOq6LSXAEH_ZNvIWvr_jG-23Gmc,2097
|
|
||||||
matplotlib/tests/test_units.py,sha256=DhE6O7PZhMUf4FMoc1ByTcMgpS9-gMmjqsiQnqBBTKc,5710
|
|
||||||
matplotlib/tests/test_usetex.py,sha256=OrkN0Alth9lTFBWJbiQDsszhW70oO6TagLaD9XsCFmo,1245
|
|
||||||
matplotlib/tests/test_widgets.py,sha256=ijPT0E0-nS1J3kBpxoWSok1GbqlZf22J5Csbto3nl4U,17654
|
|
||||||
matplotlib/tests/tinypages/.gitignore,sha256=re9gqsLda7alFAVabOwnvrzS8ChI0uTxX1FxzsvqyEE,8
|
|
||||||
matplotlib/tests/tinypages/README.md,sha256=l-sVwF8k46XxCZdwprn5wSibt6S03ICVLlMqJJN7EDo,124
|
|
||||||
matplotlib/tests/tinypages/__pycache__/conf.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/tinypages/__pycache__/range4.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/tinypages/__pycache__/range6.cpython-37.pyc,,
|
|
||||||
matplotlib/tests/tinypages/_static/.gitignore,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
||||||
matplotlib/tests/tinypages/_static/README.txt,sha256=1nnoizmUuHn5GKx8RL6MwJPlkyGmu_KHhYIMTDSWUNM,303
|
|
||||||
matplotlib/tests/tinypages/conf.py,sha256=0_a4wyqPA9oaOFpLLpSEzkZI-hwtyRbqLWBx9nf0sLA,8432
|
|
||||||
matplotlib/tests/tinypages/index.rst,sha256=kLSy7c3SoIAVsKOFkbzB4zFVzk3HW3d_rJHlHcNGBAg,446
|
|
||||||
matplotlib/tests/tinypages/range4.py,sha256=fs2krzi9sY9ysmJRQCdGs_Jh1L9vDXDrNse7c0aX_Rw,81
|
|
||||||
matplotlib/tests/tinypages/range6.py,sha256=a2EaHrNwXz4GJqhRuc7luqRpt7sqLKhTKeid9Drt2QQ,281
|
|
||||||
matplotlib/tests/tinypages/some_plots.rst,sha256=C9rwV9UVlhFvxm8VqV6PoAP1AQ8Kk0LGZI9va4joif0,2156
|
|
||||||
matplotlib/texmanager.py,sha256=kiFNpjY5S8OJ2Q6WPZ2h6YueL_zrXZQyIdrFgP_XRnI,17097
|
|
||||||
matplotlib/text.py,sha256=bt04zgIbjJUOqdZ8gomc_zWF3UOYL5mHWaHb9OxxYHM,81090
|
|
||||||
matplotlib/textpath.py,sha256=dEZ1Vg4ZUI5M4iTHn-7I45KeR1FTit78jQ-3EyK6orc,17010
|
|
||||||
matplotlib/ticker.py,sha256=Dp_BzFOaTG0Qy7W1H4-yo5JlNNLMJS2L8BiXYjCC4Xk,101242
|
|
||||||
matplotlib/tight_bbox.py,sha256=bQAOXPKfVWoBkGZbC0ckRcldgLJ8eBUe2IsT8UQpgaY,2590
|
|
||||||
matplotlib/tight_layout.py,sha256=BrNob3eytUkmtXtwgfD3jdRgNh_tIjDE89AZjAnhFdY,14586
|
|
||||||
matplotlib/transforms.py,sha256=cynqPdAO9gtYxmDBr_zr1VTSlIlbtOAwfNzGqsVV208,97572
|
|
||||||
matplotlib/tri/__init__.py,sha256=XMaejh88uov7Neu7MuYMyaNQqaxg49nXaiJfvjifrRM,256
|
|
||||||
matplotlib/tri/__pycache__/__init__.cpython-37.pyc,,
|
|
||||||
matplotlib/tri/__pycache__/triangulation.cpython-37.pyc,,
|
|
||||||
matplotlib/tri/__pycache__/tricontour.cpython-37.pyc,,
|
|
||||||
matplotlib/tri/__pycache__/trifinder.cpython-37.pyc,,
|
|
||||||
matplotlib/tri/__pycache__/triinterpolate.cpython-37.pyc,,
|
|
||||||
matplotlib/tri/__pycache__/tripcolor.cpython-37.pyc,,
|
|
||||||
matplotlib/tri/__pycache__/triplot.cpython-37.pyc,,
|
|
||||||
matplotlib/tri/__pycache__/trirefine.cpython-37.pyc,,
|
|
||||||
matplotlib/tri/__pycache__/tritools.cpython-37.pyc,,
|
|
||||||
matplotlib/tri/triangulation.py,sha256=NCY1Fx66H3MHrMA1-NW6G_shopBtFu1Ehm1f6XyRDBE,8315
|
|
||||||
matplotlib/tri/tricontour.py,sha256=4gKIAi1CFKWK8BCqAXMD6PlUKxnrC9GvzeQz0Yknvik,9794
|
|
||||||
matplotlib/tri/trifinder.py,sha256=umsDJX2kach9MVDvEirLdN9q31QQ9tdP67U71eFyGj8,3497
|
|
||||||
matplotlib/tri/triinterpolate.py,sha256=EP-ZwNC3HlOGB4jNaHGUCncXeO7LocvT2QhTr-jKCrk,64886
|
|
||||||
matplotlib/tri/tripcolor.py,sha256=H6DEToUjfU12hDkfekshYyuQoZc7Fa4r4W6MOR5d6Jw,5169
|
|
||||||
matplotlib/tri/triplot.py,sha256=aZ9O_VVLH0AOne31u11ltLlyVyhqKtyzec7WH3b3pkk,2857
|
|
||||||
matplotlib/tri/trirefine.py,sha256=uwAminHKuxgE0ZuwwllIpqK2Ww_q--VKzMicWUslA0s,13765
|
|
||||||
matplotlib/tri/tritools.py,sha256=BggcSXDVoc2mSyJp7wQ51qaw8WhdL7ianZ-D7ezkuC8,12398
|
|
||||||
matplotlib/ttconv.cpython-37m-x86_64-linux-gnu.so,sha256=DhFx2UOow2EkHvRhRhsIYL-lCKzlfCA9nAKyB8_lZpA,83888
|
|
||||||
matplotlib/type1font.py,sha256=-D1P81hhDUVNAHZ55-Df4cPc-3R8ycY_judVBZphgsk,12168
|
|
||||||
matplotlib/units.py,sha256=dgSbQsrJPRiKf5IJv-PM0xYMcvT3kle3gdPJsdjbRZk,7332
|
|
||||||
matplotlib/widgets.py,sha256=lMHpWCFdFTwSCEO5uL4fjcsoDQMzkzlWyVXnx80FVn4,94615
|
|
||||||
mpl_toolkits/axes_grid/__init__.py,sha256=VLlc0DaOkr9JumPa8W4zt9lGHp180ie8_WLPZVNSJMw,537
|
|
||||||
mpl_toolkits/axes_grid/__pycache__/__init__.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axes_grid/__pycache__/anchored_artists.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axes_grid/__pycache__/angle_helper.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axes_grid/__pycache__/axes_divider.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axes_grid/__pycache__/axes_grid.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axes_grid/__pycache__/axes_rgb.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axes_grid/__pycache__/axes_size.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axes_grid/__pycache__/axis_artist.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axes_grid/__pycache__/axisline_style.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axes_grid/__pycache__/axislines.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axes_grid/__pycache__/clip_path.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axes_grid/__pycache__/colorbar.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axes_grid/__pycache__/floating_axes.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axes_grid/__pycache__/grid_finder.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axes_grid/__pycache__/grid_helper_curvelinear.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axes_grid/__pycache__/inset_locator.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axes_grid/__pycache__/parasite_axes.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axes_grid/anchored_artists.py,sha256=_F6-9iacZidb5JpJ8jCOZ9PdiZaR5qpfBjf-3VjTzNc,291
|
|
||||||
mpl_toolkits/axes_grid/angle_helper.py,sha256=Tb4Mb_NGkUdkisebe2dqfBdFmUZiSmGyUnftiSeSIls,51
|
|
||||||
mpl_toolkits/axes_grid/axes_divider.py,sha256=tJlPia3Z8xLq6uXehBwAlD_4ywMvRTTkM73qNnCpo7Q,178
|
|
||||||
mpl_toolkits/axes_grid/axes_grid.py,sha256=UPlVDwsze_w2aZeLaMg4WZVK3q2EvWePXTFZFvjCQz4,89
|
|
||||||
mpl_toolkits/axes_grid/axes_rgb.py,sha256=d3h2tImoPxvVtl8i4IBA_i1vBQykZDYizcNDGdjRltE,201
|
|
||||||
mpl_toolkits/axes_grid/axes_size.py,sha256=v4Nhxe7DVp1FkKX03DqJJ1aevDanDvgKT9r0ouDzTxw,48
|
|
||||||
mpl_toolkits/axes_grid/axis_artist.py,sha256=zUlJFUHueDsMtzLi_mK2_Wf-nSBQgiTsMOFpo_SngZ0,50
|
|
||||||
mpl_toolkits/axes_grid/axisline_style.py,sha256=lNVHXkFWhSWPXOOfF-wlVkDPzmzuStJyJzF-NS5Wf_g,53
|
|
||||||
mpl_toolkits/axes_grid/axislines.py,sha256=kVyhb6laiImmuNE53QTQh3kgxz0sO1mcSMpnqIdjylA,48
|
|
||||||
mpl_toolkits/axes_grid/clip_path.py,sha256=s-d36hUiy9I9BSr9wpxjgoAACCQrczHjw072JvArNvE,48
|
|
||||||
mpl_toolkits/axes_grid/colorbar.py,sha256=DckRf6tadLeTNjx-Zk1u3agnSGZgizDjd0Dxw1-GRdw,171
|
|
||||||
mpl_toolkits/axes_grid/floating_axes.py,sha256=i35OfV1ZMF-DkLo4bKmzFZP6LgCwXfdDKxYlGqjyKOM,52
|
|
||||||
mpl_toolkits/axes_grid/grid_finder.py,sha256=Y221c-Jh_AFd3Oolzvr0B1Zrz9MoXPatUABQdLsFdpw,50
|
|
||||||
mpl_toolkits/axes_grid/grid_helper_curvelinear.py,sha256=nRl_B-755X7UpVqqdwkqc_IwiTmM48z3eOMHuvJT5HI,62
|
|
||||||
mpl_toolkits/axes_grid/inset_locator.py,sha256=qqXlT8JWokP0kV-8NHknZDINtK-jbXfkutH_1tcRe_o,216
|
|
||||||
mpl_toolkits/axes_grid/parasite_axes.py,sha256=kCFtaRTd0O8ePL78GOYvhEKqn8rE9bk61v0kVgMb6UE,469
|
|
||||||
mpl_toolkits/axes_grid1/__init__.py,sha256=-lw0ZfG4XUpuAolCpXKFwtS3w1LJ1ZToSEC9OSmB-4Q,204
|
|
||||||
mpl_toolkits/axes_grid1/__pycache__/__init__.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axes_grid1/__pycache__/anchored_artists.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axes_grid1/__pycache__/axes_divider.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axes_grid1/__pycache__/axes_grid.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axes_grid1/__pycache__/axes_rgb.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axes_grid1/__pycache__/axes_size.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axes_grid1/__pycache__/colorbar.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axes_grid1/__pycache__/inset_locator.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axes_grid1/__pycache__/mpl_axes.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axes_grid1/__pycache__/parasite_axes.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axes_grid1/anchored_artists.py,sha256=F9396ifiWLedXEsivC3-rJjhYOxZ84dHYFhlRMVt4wE,21031
|
|
||||||
mpl_toolkits/axes_grid1/axes_divider.py,sha256=rZOhnowUzJ3mXb6LKkLPjDyxkz-EPJmA3MCafFa8VN8,29175
|
|
||||||
mpl_toolkits/axes_grid1/axes_grid.py,sha256=2ThJGeKXb9avu0KN3ujBliY2HV26IHC1daxy74t8ITk,27888
|
|
||||||
mpl_toolkits/axes_grid1/axes_rgb.py,sha256=NsMKkaMEeXd6N1AYVP1Pz-ulwNeof1pU4qkReoQ8xFc,6652
|
|
||||||
mpl_toolkits/axes_grid1/axes_size.py,sha256=YBC1PUmUK1-0c7cuqgJQBpDwVrbZQaWXyWadvuOO5bs,8602
|
|
||||||
mpl_toolkits/axes_grid1/colorbar.py,sha256=Y0-Uf9osbz31YBOTxxs_UFXbp6Xyc9Rais47tBMjTXI,27123
|
|
||||||
mpl_toolkits/axes_grid1/inset_locator.py,sha256=0BA8z3BiT78sS2-ksVe8iKS6KLxVv_NTV38NTLmRuu4,23675
|
|
||||||
mpl_toolkits/axes_grid1/mpl_axes.py,sha256=MJVYUN4YRtTWrq1wmyv_y61O002tiyFESmBSaJ8xkG4,4380
|
|
||||||
mpl_toolkits/axes_grid1/parasite_axes.py,sha256=ug0YRJiTtA3YVikdKMGj-qjoeOFnqNw2QnRab0Qp7wI,13570
|
|
||||||
mpl_toolkits/axisartist/__init__.py,sha256=2zsgjqTtP_NXv78MEaKabmfmkjA7yhy77pIcaR57YWs,748
|
|
||||||
mpl_toolkits/axisartist/__pycache__/__init__.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axisartist/__pycache__/angle_helper.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axisartist/__pycache__/axes_divider.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axisartist/__pycache__/axes_grid.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axisartist/__pycache__/axes_rgb.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axisartist/__pycache__/axis_artist.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axisartist/__pycache__/axisline_style.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axisartist/__pycache__/axislines.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axisartist/__pycache__/clip_path.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axisartist/__pycache__/floating_axes.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axisartist/__pycache__/grid_finder.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axisartist/__pycache__/grid_helper_curvelinear.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axisartist/__pycache__/parasite_axes.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/axisartist/angle_helper.py,sha256=KZiXfi0IPcGp6JFXewj0VLrUycSfI93ezoimkti3wpY,12632
|
|
||||||
mpl_toolkits/axisartist/axes_divider.py,sha256=baPCBjM20SvAUeMjhvlS_cccRSM1y7ZKybtoW8upo2k,127
|
|
||||||
mpl_toolkits/axisartist/axes_grid.py,sha256=vfd_EXHuYQ7iIVK2FOm6inLhb7huZxtOSvFyOVW2GmU,610
|
|
||||||
mpl_toolkits/axisartist/axes_rgb.py,sha256=TpJCB8eA0wHZVXOxxfFoy1Tk_KFj68sZvo74doDeHYE,179
|
|
||||||
mpl_toolkits/axisartist/axis_artist.py,sha256=gScMYbfAyxT5IgyEZRVto2NyZVLGpDQeJ1t9tk1d3OM,43453
|
|
||||||
mpl_toolkits/axisartist/axisline_style.py,sha256=bQ3M5gAxS7HbCC3oOQgrSyNWdk_FbvXfX24Eatge0UE,5098
|
|
||||||
mpl_toolkits/axisartist/axislines.py,sha256=mrQIihqbfBi2F-QgLRjZvHGM6rEojStBzojYpVNkjg0,20852
|
|
||||||
mpl_toolkits/axisartist/clip_path.py,sha256=LE_IIP0byNr5ELJlD8_8fsAh215MUDoK19-BISuFB80,3777
|
|
||||||
mpl_toolkits/axisartist/floating_axes.py,sha256=xSAJ5Myaa5Xm9DkOhJcdaPwzdPyvJnw5K9YPmDwB5ME,13122
|
|
||||||
mpl_toolkits/axisartist/grid_finder.py,sha256=K1Gae38Jt2OFfScZaKbxkLLcWrHDm-2bAVsl56SC1F0,10388
|
|
||||||
mpl_toolkits/axisartist/grid_helper_curvelinear.py,sha256=6QT9nTQ2dJ_NPsazS0Q0hC8W5IV7yzqYd_Fa8_gJXmI,14384
|
|
||||||
mpl_toolkits/axisartist/parasite_axes.py,sha256=1sQwBEYuXHpaEeObb7cXh0I1xWroYtcvFiEmwrzqK3w,447
|
|
||||||
mpl_toolkits/mplot3d/__init__.py,sha256=V2iPIP9VyRhoJsFWnQf5AkfyI1GSSP9H6hICEe9edJo,27
|
|
||||||
mpl_toolkits/mplot3d/__pycache__/__init__.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/mplot3d/__pycache__/art3d.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/mplot3d/__pycache__/axes3d.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/mplot3d/__pycache__/axis3d.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/mplot3d/__pycache__/proj3d.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/mplot3d/art3d.py,sha256=MAR_fFyBwe3VkwlOeWMccwDWo8RR1VqhUjuipLPuIFU,27647
|
|
||||||
mpl_toolkits/mplot3d/axes3d.py,sha256=iJ7LN-UKY7xMaGjYbeu-J1IuC54QX3irx7Kkh5gInzY,98609
|
|
||||||
mpl_toolkits/mplot3d/axis3d.py,sha256=UdxPxUW7GDoOpBy4uByLmLZJfle2wu0oYGenDHjjcLA,16737
|
|
||||||
mpl_toolkits/mplot3d/proj3d.py,sha256=5xwjogevdUCBaV9sx1RlNqO6fMCSIBi_1_uVZniy2pU,5499
|
|
||||||
mpl_toolkits/tests/__init__.py,sha256=iPdasxJf0vpIi11tQ98OVSQgS0UaPUyOEGGfAryAhIA,381
|
|
||||||
mpl_toolkits/tests/__pycache__/__init__.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/tests/__pycache__/conftest.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/tests/__pycache__/test_axes_grid.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/tests/__pycache__/test_axes_grid1.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/tests/__pycache__/test_axisartist_angle_helper.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/tests/__pycache__/test_axisartist_axis_artist.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/tests/__pycache__/test_axisartist_axislines.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/tests/__pycache__/test_axisartist_clip_path.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/tests/__pycache__/test_axisartist_floating_axes.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/tests/__pycache__/test_axisartist_grid_finder.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/tests/__pycache__/test_axisartist_grid_helper_curvelinear.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/tests/__pycache__/test_mplot3d.cpython-37.pyc,,
|
|
||||||
mpl_toolkits/tests/baseline_images/test_axes_grid/imagegrid_cbar_mode.png,sha256=yvo6erXXc3Z9aO0rrEezBooCc6KhAw7wKv4WngOQmFA,87393
|
|
||||||
mpl_toolkits/tests/baseline_images/test_axes_grid1/anchored_direction_arrows.png,sha256=XMZGgG7_9k96bKhI2G--XBVKpct5O5psbGH2Wvj5YA0,10784
|
|
||||||
mpl_toolkits/tests/baseline_images/test_axes_grid1/anchored_direction_arrows_many_args.png,sha256=fkPsdmhd4S1g-QxMb55M63iAgWmC2G4ytcLOT9tMAD0,11039
|
|
||||||
mpl_toolkits/tests/baseline_images/test_axes_grid1/divider_append_axes.pdf,sha256=eW2CuM_T4d95dC-DU0PmmQD7gqRQIO0rcQpvp-zu1i4,25446
|
|
||||||
mpl_toolkits/tests/baseline_images/test_axes_grid1/divider_append_axes.png,sha256=VfRfs6p4akgjGxxNm6Bu83Pg0v1KmU7WPu97_-kzNFc,48825
|
|
||||||
mpl_toolkits/tests/baseline_images/test_axes_grid1/divider_append_axes.svg,sha256=usfsa3y-s-N2KMOzsOZHTq-PZXgAPXsSM-lkxJ3ZUi0,172812
|
|
||||||
mpl_toolkits/tests/baseline_images/test_axes_grid1/fill_facecolor.png,sha256=Tkrylxebxm8SuWZjQK0qXSX8m9QsQU6kYm7L2dgt4yg,14845
|
|
||||||
mpl_toolkits/tests/baseline_images/test_axes_grid1/image_grid.png,sha256=HIg43mbdOUyEWY-jQ1DEpG7DMqCcWbX1Xf2itmW1YL4,3786
|
|
||||||
mpl_toolkits/tests/baseline_images/test_axes_grid1/inset_axes.png,sha256=RQmR39E6Vskvl7G4LInHibW9E1VK0QgCvI-hBlb-E2E,9928
|
|
||||||
mpl_toolkits/tests/baseline_images/test_axes_grid1/inset_locator.png,sha256=bQKKKUuoU_EZwZT_9FzzeVKsKwUUBOZV55g4vVUbnCU,9490
|
|
||||||
mpl_toolkits/tests/baseline_images/test_axes_grid1/inverted_zoomed_axes.png,sha256=rvglsLg8Kl9jE_JukTJ5B3EHozsIYJsaYA0JIOicZL8,25997
|
|
||||||
mpl_toolkits/tests/baseline_images/test_axes_grid1/twin_axes_empty_and_removed.png,sha256=0YzkFhxs4SBG_FEmnWB10bXIxl9aq7WJveQAqHm0JrQ,37701
|
|
||||||
mpl_toolkits/tests/baseline_images/test_axes_grid1/zoomed_axes.png,sha256=mUu8zJtz8FMb7h5l4Cfp3oBi9jaNR5OoyaDgwqpAZp4,25893
|
|
||||||
mpl_toolkits/tests/baseline_images/test_axisartist_axis_artist/axis_artist.png,sha256=qdlk9UPScCAN9RBOhoNqLmJvmkXt8pCuwuQtrz5E8Bs,10151
|
|
||||||
mpl_toolkits/tests/baseline_images/test_axisartist_axis_artist/axis_artist_labelbase.png,sha256=An5lovtvAiNA1NZI-E8kOj6eYTruQMqwf3J7pXwdk4A,10598
|
|
||||||
mpl_toolkits/tests/baseline_images/test_axisartist_axis_artist/axis_artist_ticklabels.png,sha256=7vuAKkIqcpgJrc2AF7oslf-E_sDfSlCoymyc87u4AWs,5696
|
|
||||||
mpl_toolkits/tests/baseline_images/test_axisartist_axis_artist/axis_artist_ticks.png,sha256=CkVtCWG13ViW0w2DsbzfXSvoFWHYaaqQYeEYpbKbOg8,5695
|
|
||||||
mpl_toolkits/tests/baseline_images/test_axisartist_axislines/ParasiteAxesAuxTrans_meshplot.png,sha256=FOgl-Glmzhdp6V8mz4StofTsFXGysFkEcUeaWtmJDZs,34354
|
|
||||||
mpl_toolkits/tests/baseline_images/test_axisartist_axislines/Subplot.png,sha256=tRpYCjR5zUkafA85DVmY3duTEouwCZq6jDwSF4UsBS8,26919
|
|
||||||
mpl_toolkits/tests/baseline_images/test_axisartist_axislines/SubplotZero.png,sha256=3kCrz7HQMYrK3iDgYgf8kyigxRtIGFBbcUzJPtiXh_E,28682
|
|
||||||
mpl_toolkits/tests/baseline_images/test_axisartist_clip_path/clip_path.png,sha256=BtMyb7ZawcgId9jl1_qW72lU_ZyxLN780uQ9bCLjbHA,25701
|
|
||||||
mpl_toolkits/tests/baseline_images/test_axisartist_floating_axes/curvelinear3.png,sha256=4th7Y74_9YV6X25RqJW0Op9WDzGRCcxF1kfNogkgozE,52835
|
|
||||||
mpl_toolkits/tests/baseline_images/test_axisartist_floating_axes/curvelinear4.png,sha256=cYjrSiH6Mvor-VhmwNUgX7Le3_k1rurpd8L5vhTf16s,29374
|
|
||||||
mpl_toolkits/tests/baseline_images/test_axisartist_grid_helper_curvelinear/axis_direction.png,sha256=3fue92dg-ntYI0XX0nB31IFpgRT2V3izqjrmLvEdYN4,40536
|
|
||||||
mpl_toolkits/tests/baseline_images/test_axisartist_grid_helper_curvelinear/custom_transform.png,sha256=4cQhIFK1z8oPUVyvkHNZ_m-GCbikmUbTvkvYVGy6U4o,15118
|
|
||||||
mpl_toolkits/tests/baseline_images/test_axisartist_grid_helper_curvelinear/polar_box.png,sha256=wWaPM3I7_435SkVQqIggb8BHrWBMWrsSVyMZQQJ6fE4,62526
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/axes3d_cla.png,sha256=htnP1CA8dd85KqdnOsHVlsehT90MUoQD8kFTyra0AuE,51409
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/axes3d_labelpad.png,sha256=zrLsk8t7s970yaY3cqj6SOMbI6UY8Loe0Zbp0WqFtwQ,66817
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/axes3d_ortho.png,sha256=SoyN30SsuvEECZyB_ReGP3ZKGZJazOp05dXa3YUn7Jc,47796
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/bar3d.png,sha256=Qw909B4nDmV9DlMuo1DKk7y5ndjtvni5d_DcysmG9VA,100466
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/bar3d_notshaded.png,sha256=soaHKytaVZHmPvHIEcPFQDJDqhEEuNO_JIVCZyjacxM,66294
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/bar3d_shaded.png,sha256=laBssZyuviouRe3seffJWOz45OLunXC0dFHi-lYge1w,115939
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/contour3d.png,sha256=tii1IakS8MC_Vuwd95HhcyM0iq4zGN5DxgRFfB9mKu8,83161
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/contourf3d.png,sha256=Jb-fhAcgogE8jn9DSsaqInUfWC7D_5Pf3QRf7XWAX2Q,42575
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/contourf3d_fill.png,sha256=dE8eHoj43eePB44F1nLM2RLj8iqw8rCYI3D0VD3gUg0,39694
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/lines3d.png,sha256=DQT-NruHCeG5LKpjG-dlLln3aCoPKhua5PQnHTafBGU,60217
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/mixedsubplot.png,sha256=iHxYbxRflxIpjoAtWo9KAvgK4CS-k4N03p0SX_xF4DA,39674
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/plot_3d_from_2d.png,sha256=AWos5EJWMerD0tgVZyvBofz-5hnCq6fhGHKmQi-izAg,56593
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/poly3dcollection_alpha.png,sha256=AnZJbnnBnF_fny5FBTlSWblkNMlPI1dcQRlCfGPIjWI,52046
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/poly3dcollection_closed.png,sha256=ePzSA-iFaQbmH603vw1jhs9vyIt45xXnbpIuUF3a1l8,52065
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/proj3d_axes_cube.png,sha256=AJ0EoayvdBoywpOUWcxbMQ0oB7cTzcoWGgGyx2qgQMU,23182
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/proj3d_axes_cube_ortho.png,sha256=5Phz7BclSciZpg4SDu-eUQ-v_ikHbEqReQWCdeHywQk,16210
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/proj3d_lines_dists.png,sha256=XCd4hX2ckc5GCxcgenkRJ8MT7pX-3iMLylD2rCjNl-4,18898
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/quiver3d.png,sha256=PBllNI1kHf1rz-oPK507OwsPNE9DPwivXAVJM9DemBI,104755
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/quiver3d_empty.png,sha256=98D3k5QIL7KugUwzqJhdLtp9dgDGgx8hGa9_u8cvX6o,37954
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/quiver3d_masked.png,sha256=67yp7-6f-vDiYTmCqMFfuIEGly5UHCCUOV84YJtLsX8,80392
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/quiver3d_pivot_middle.png,sha256=N4o26wMzfnyxndPbZ2VnsjIAiNYrFN9Aa40ficwO9AM,104735
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/quiver3d_pivot_tail.png,sha256=Ff_UrWxD-VIMQLN1uXy5u_Yd5e1P427YfGM05nvU2kE,104951
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/scatter3d.png,sha256=MDaocusHz6Itinjm2j6fnDh-rl1fqVjnqM89nP8bwZs,43155
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/scatter3d_color.png,sha256=Y7De9BIFLp0Ova4fk9IcXloNjiwmifTrFA1IfVJA3aE,41598
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/surface3d.png,sha256=Ok0UmO2DELze2yK8mRx0CifmRAgvjyS1IvERsBRvFlU,54712
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/surface3d_shaded.png,sha256=kWYGPWgG1ZrQVgd389xmIZ1cc59tAkKKiikKaJzHKkw,43474
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/text3d.png,sha256=sO68K3cti2YsPkkjEIAvc7_pd8JaHpc_a78UVx4Htu4,78758
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/tricontour.png,sha256=8IjYmJP6cBhnPGLz-WDyn7UUMYZ10Kz2MpjOFwDUVow,71328
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/trisurf3d.png,sha256=nO0gJBIluLEX3mlxXY3C6bx-9Jf_xJyXAnTXKnqrIkQ,99103
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/trisurf3d_shaded.png,sha256=LSVF3lI7JnYXmCBAcn410k3JRE-3ssp84Dmgg3zr0FA,94328
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/voxels-alpha.png,sha256=LELjsQnfvfzLF8rNSh5azv9BdwF8TlCMn2wbBJNTtyQ,178141
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/voxels-edge-style.png,sha256=UJXpFMSWIFgUH2rLEv1nxDvHrnshlSz4d5ZB34upa3g,65759
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/voxels-named-colors.png,sha256=J8m66Bc5NoeZxGRwbBThV06_aybNvMeTtwUnmCRzNak,93580
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/voxels-rgb-data.png,sha256=5s02No0RWv8NYV_ccFUnDdBaUHQ8DTO90qddKBnN6mw,131458
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/voxels-simple.png,sha256=7VCcyzKKKz8E7txQV4wi-jEbtftaFW_ekWmA9E1qx3Y,60304
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/voxels-xyz.png,sha256=KwDmkuK7FMtl0Q2ank7wcph9uTncUr7UdTh2hUYdZP8,121446
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/wireframe3d.png,sha256=epmsR4rWGzh7prW3RL_t8ZcUEsphM5bc0t5j__iauOY,108371
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/wireframe3dzerocstride.png,sha256=WaO_3NcaZPFzlui5SQYJ-TbUylHkSbieneCYPffNgAA,81117
|
|
||||||
mpl_toolkits/tests/baseline_images/test_mplot3d/wireframe3dzerorstride.png,sha256=y1JvfuVOBiNhJoJ2HdOXyBYBBkQm-oaPcoekfT-cMso,84284
|
|
||||||
mpl_toolkits/tests/conftest.py,sha256=Ph6QZKdfAnkPwU52StddC-uwtCHfANKX1dDXgtX122g,213
|
|
||||||
mpl_toolkits/tests/test_axes_grid.py,sha256=SUnj9aImCEI-Q3_cM8e5BlizoNle9E1joKkE_q57OAg,2694
|
|
||||||
mpl_toolkits/tests/test_axes_grid1.py,sha256=pUw19PTds6WRlLON5U9ZWmt6HxV56Q6DKDPVGM34ysk,17113
|
|
||||||
mpl_toolkits/tests/test_axisartist_angle_helper.py,sha256=PwhJwBm2kk4uMyhdO5arQs8IlqSX2vN0hvUzI7YHqrw,5670
|
|
||||||
mpl_toolkits/tests/test_axisartist_axis_artist.py,sha256=N4Khx8jSxkoiMz3KvumodmFKHZUtdwtjkzxLWPSdyuw,3008
|
|
||||||
mpl_toolkits/tests/test_axisartist_axislines.py,sha256=4ujhndnDq-6albE4WwVFTVURfjG1xK1597smUGMxfFg,2331
|
|
||||||
mpl_toolkits/tests/test_axisartist_clip_path.py,sha256=afS3nvNqCgvDpJdg_MvbwydtSWv5b6ciP-Iq2aNcNFQ,1004
|
|
||||||
mpl_toolkits/tests/test_axisartist_floating_axes.py,sha256=xENnUpFU8EHPgnON6W1xqMVWIq8qxIzuGf1oMmSMFJo,4127
|
|
||||||
mpl_toolkits/tests/test_axisartist_grid_finder.py,sha256=e65sLudWFIXeU08Sis3_SI1JEI6eq8YqKj-80F_Nohk,325
|
|
||||||
mpl_toolkits/tests/test_axisartist_grid_helper_curvelinear.py,sha256=0AT6TdbxHGHlircgjNZyK2u1dw05YLXdOhLqXmsKyw4,7572
|
|
||||||
mpl_toolkits/tests/test_mplot3d.py,sha256=TojtKh1gbRWl-kCWQcYaFMOS89txDRd02O0NBJuu-vE,31991
|
|
||||||
pylab.py,sha256=u_By3CHla-rBMg57egFXIxZ3P_J6zEkSu_dNpBcH5pw,90
|
|
|
@ -1,5 +0,0 @@
|
||||||
Wheel-Version: 1.0
|
|
||||||
Generator: bdist_wheel (0.31.1)
|
|
||||||
Root-Is-Purelib: false
|
|
||||||
Tag: cp37-cp37m-manylinux1_x86_64
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
mpl_toolkits
|
|
|
@ -1,3 +0,0 @@
|
||||||
matplotlib
|
|
||||||
mpl_toolkits
|
|
||||||
pylab
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -11,8 +11,8 @@ version_json = '''
|
||||||
{
|
{
|
||||||
"dirty": false,
|
"dirty": false,
|
||||||
"error": null,
|
"error": null,
|
||||||
"full-revisionid": "ca3d653536dec38a0c1ac3b80413961ca1bcdda6",
|
"full-revisionid": "a1a5298b0d4a8d8230103d0fa8d369fca7fdeea0",
|
||||||
"version": "3.2.1"
|
"version": "3.2.2"
|
||||||
}
|
}
|
||||||
''' # END VERSION_JSON
|
''' # END VERSION_JSON
|
||||||
|
|
||||||
|
|
|
@ -1099,7 +1099,7 @@ class Animation:
|
||||||
extra_args=extra_args,
|
extra_args=extra_args,
|
||||||
metadata=metadata)
|
metadata=metadata)
|
||||||
else:
|
else:
|
||||||
alt_writer = next(writers, None)
|
alt_writer = next(iter(writers), None)
|
||||||
if alt_writer is None:
|
if alt_writer is None:
|
||||||
raise ValueError("Cannot save animation: no writers are "
|
raise ValueError("Cannot save animation: no writers are "
|
||||||
"available. Please install ffmpeg to "
|
"available. Please install ffmpeg to "
|
||||||
|
|
|
@ -654,6 +654,7 @@ class Axes(_AxesBase):
|
||||||
raise ValueError('secondary_xaxis location must be either '
|
raise ValueError('secondary_xaxis location must be either '
|
||||||
'a float or "top"/"bottom"')
|
'a float or "top"/"bottom"')
|
||||||
|
|
||||||
|
@docstring.dedent_interpd
|
||||||
def secondary_yaxis(self, location, *, functions=None, **kwargs):
|
def secondary_yaxis(self, location, *, functions=None, **kwargs):
|
||||||
"""
|
"""
|
||||||
Add a second y-axis to this axes.
|
Add a second y-axis to this axes.
|
||||||
|
@ -4211,19 +4212,26 @@ class Axes(_AxesBase):
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass # Failed to convert to float array; must be color specs.
|
pass # Failed to convert to float array; must be color specs.
|
||||||
else:
|
else:
|
||||||
|
# handle the documented special case of a 2D array with 1
|
||||||
|
# row which as RGB(A) to broadcast.
|
||||||
|
if c.shape == (1, 4) or c.shape == (1, 3):
|
||||||
|
c_is_mapped = False
|
||||||
|
if c.size != xsize:
|
||||||
|
valid_shape = False
|
||||||
# If c can be either mapped values or a RGB(A) color, prefer
|
# If c can be either mapped values or a RGB(A) color, prefer
|
||||||
# the former if shapes match, the latter otherwise.
|
# the former if shapes match, the latter otherwise.
|
||||||
if c.size == xsize:
|
elif c.size == xsize:
|
||||||
c = c.ravel()
|
c = c.ravel()
|
||||||
c_is_mapped = True
|
c_is_mapped = True
|
||||||
else: # Wrong size; it must not be intended for mapping.
|
else: # Wrong size; it must not be intended for mapping.
|
||||||
if c.shape in ((3,), (4,)):
|
if c.shape in ((3,), (4,)):
|
||||||
_log.warning(
|
_log.warning(
|
||||||
"'c' argument looks like a single numeric RGB or "
|
"*c* argument looks like a single numeric RGB or "
|
||||||
"RGBA sequence, which should be avoided as value-"
|
"RGBA sequence, which should be avoided as value-"
|
||||||
"mapping will have precedence in case its length "
|
"mapping will have precedence in case its length "
|
||||||
"matches with 'x' & 'y'. Please use a 2-D array "
|
"matches with *x* & *y*. Please use the *color* "
|
||||||
"with a single row if you really want to specify "
|
"keyword-argument or provide a 2-D array "
|
||||||
|
"with a single row if you intend to specify "
|
||||||
"the same RGB or RGBA value for all points.")
|
"the same RGB or RGBA value for all points.")
|
||||||
valid_shape = False
|
valid_shape = False
|
||||||
if not c_is_mapped:
|
if not c_is_mapped:
|
||||||
|
@ -4267,14 +4275,14 @@ class Axes(_AxesBase):
|
||||||
The marker size in points**2.
|
The marker size in points**2.
|
||||||
Default is ``rcParams['lines.markersize'] ** 2``.
|
Default is ``rcParams['lines.markersize'] ** 2``.
|
||||||
|
|
||||||
c : color, sequence, or sequence of colors, optional
|
c : array-like or list of colors or color, optional
|
||||||
The marker color. Possible values:
|
The marker colors. Possible values:
|
||||||
|
|
||||||
- A single color format string.
|
|
||||||
- A sequence of colors of length n.
|
|
||||||
- A scalar or sequence of n numbers to be mapped to colors using
|
- A scalar or sequence of n numbers to be mapped to colors using
|
||||||
*cmap* and *norm*.
|
*cmap* and *norm*.
|
||||||
- A 2-D array in which the rows are RGB or RGBA.
|
- A 2-D array in which the rows are RGB or RGBA.
|
||||||
|
- A sequence of colors of length n.
|
||||||
|
- A single color format string.
|
||||||
|
|
||||||
Note that *c* should not be a single numeric RGB or RGBA sequence
|
Note that *c* should not be a single numeric RGB or RGBA sequence
|
||||||
because that is indistinguishable from an array of values to be
|
because that is indistinguishable from an array of values to be
|
||||||
|
@ -4283,9 +4291,12 @@ class Axes(_AxesBase):
|
||||||
matching will have precedence in case of a size matching with *x*
|
matching will have precedence in case of a size matching with *x*
|
||||||
and *y*.
|
and *y*.
|
||||||
|
|
||||||
Defaults to ``None``. In that case the marker color is determined
|
If you wish to specify a single color for all points
|
||||||
by the value of ``color``, ``facecolor`` or ``facecolors``. In case
|
prefer the *color* keyword argument.
|
||||||
those are not specified or ``None``, the marker color is determined
|
|
||||||
|
Defaults to `None`. In that case the marker color is determined
|
||||||
|
by the value of *color*, *facecolor* or *facecolors*. In case
|
||||||
|
those are not specified or `None`, the marker color is determined
|
||||||
by the next color of the ``Axes``' current "shape and fill" color
|
by the next color of the ``Axes``' current "shape and fill" color
|
||||||
cycle. This cycle defaults to :rc:`axes.prop_cycle`.
|
cycle. This cycle defaults to :rc:`axes.prop_cycle`.
|
||||||
|
|
||||||
|
|
|
@ -3220,6 +3220,9 @@ class _AxesBase(martist.Artist):
|
||||||
left, right = sorted([left, right], reverse=bool(reverse))
|
left, right = sorted([left, right], reverse=bool(reverse))
|
||||||
|
|
||||||
self._viewLim.intervalx = (left, right)
|
self._viewLim.intervalx = (left, right)
|
||||||
|
# Mark viewlims as no longer stale without triggering an autoscale.
|
||||||
|
for ax in self._shared_x_axes.get_siblings(self):
|
||||||
|
ax._stale_viewlim_x = False
|
||||||
if auto is not None:
|
if auto is not None:
|
||||||
self._autoscaleXon = bool(auto)
|
self._autoscaleXon = bool(auto)
|
||||||
|
|
||||||
|
@ -3611,6 +3614,9 @@ class _AxesBase(martist.Artist):
|
||||||
bottom, top = sorted([bottom, top], reverse=bool(reverse))
|
bottom, top = sorted([bottom, top], reverse=bool(reverse))
|
||||||
|
|
||||||
self._viewLim.intervaly = (bottom, top)
|
self._viewLim.intervaly = (bottom, top)
|
||||||
|
# Mark viewlims as no longer stale without triggering an autoscale.
|
||||||
|
for ax in self._shared_y_axes.get_siblings(self):
|
||||||
|
ax._stale_viewlim_y = False
|
||||||
if auto is not None:
|
if auto is not None:
|
||||||
self._autoscaleYon = bool(auto)
|
self._autoscaleYon = bool(auto)
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ graphics contexts must implement to serve as a matplotlib backend
|
||||||
The base class for the messaging area.
|
The base class for the messaging area.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager, suppress
|
||||||
from enum import IntEnum
|
from enum import IntEnum
|
||||||
import functools
|
import functools
|
||||||
import importlib
|
import importlib
|
||||||
|
@ -52,6 +52,7 @@ from matplotlib import (
|
||||||
from matplotlib._pylab_helpers import Gcf
|
from matplotlib._pylab_helpers import Gcf
|
||||||
from matplotlib.transforms import Affine2D
|
from matplotlib.transforms import Affine2D
|
||||||
from matplotlib.path import Path
|
from matplotlib.path import Path
|
||||||
|
from matplotlib.cbook import _setattr_cm
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from PIL import __version__ as PILLOW_VERSION
|
from PIL import __version__ as PILLOW_VERSION
|
||||||
|
@ -712,6 +713,23 @@ class RendererBase:
|
||||||
Currently only supported by the agg renderer.
|
Currently only supported by the agg renderer.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def _draw_disabled(self):
|
||||||
|
"""
|
||||||
|
Context manager to temporary disable drawing.
|
||||||
|
|
||||||
|
This is used for getting the drawn size of Artists. This lets us
|
||||||
|
run the draw process to update any Python state but does not pay the
|
||||||
|
cost of the draw_XYZ calls on the canvas.
|
||||||
|
"""
|
||||||
|
no_ops = {
|
||||||
|
meth_name: lambda *args, **kwargs: None
|
||||||
|
for meth_name in dir(RendererBase)
|
||||||
|
if (meth_name.startswith("draw_")
|
||||||
|
or meth_name in ["open_group", "close_group"])
|
||||||
|
}
|
||||||
|
|
||||||
|
return _setattr_cm(self, **no_ops)
|
||||||
|
|
||||||
|
|
||||||
class GraphicsContextBase:
|
class GraphicsContextBase:
|
||||||
"""An abstract base class that provides color, line styles, etc."""
|
"""An abstract base class that provides color, line styles, etc."""
|
||||||
|
@ -1420,7 +1438,6 @@ class MouseEvent(LocationEvent):
|
||||||
(*x*, *y*) in figure coords ((0, 0) = bottom left)
|
(*x*, *y*) in figure coords ((0, 0) = bottom left)
|
||||||
button pressed None, 1, 2, 3, 'up', 'down'
|
button pressed None, 1, 2, 3, 'up', 'down'
|
||||||
"""
|
"""
|
||||||
LocationEvent.__init__(self, name, canvas, x, y, guiEvent=guiEvent)
|
|
||||||
if button in MouseButton.__members__.values():
|
if button in MouseButton.__members__.values():
|
||||||
button = MouseButton(button)
|
button = MouseButton(button)
|
||||||
self.button = button
|
self.button = button
|
||||||
|
@ -1428,6 +1445,10 @@ class MouseEvent(LocationEvent):
|
||||||
self.step = step
|
self.step = step
|
||||||
self.dblclick = dblclick
|
self.dblclick = dblclick
|
||||||
|
|
||||||
|
# super-init is deferred to the end because it calls back on
|
||||||
|
# 'axes_enter_event', which requires a fully initialized event.
|
||||||
|
LocationEvent.__init__(self, name, canvas, x, y, guiEvent=guiEvent)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return (f"{self.name}: "
|
return (f"{self.name}: "
|
||||||
f"xy=({self.x}, {self.y}) xydata=({self.xdata}, {self.ydata}) "
|
f"xy=({self.x}, {self.y}) xydata=({self.xdata}, {self.ydata}) "
|
||||||
|
@ -1512,19 +1533,19 @@ class KeyEvent(LocationEvent):
|
||||||
cid = fig.canvas.mpl_connect('key_press_event', on_key)
|
cid = fig.canvas.mpl_connect('key_press_event', on_key)
|
||||||
"""
|
"""
|
||||||
def __init__(self, name, canvas, key, x=0, y=0, guiEvent=None):
|
def __init__(self, name, canvas, key, x=0, y=0, guiEvent=None):
|
||||||
LocationEvent.__init__(self, name, canvas, x, y, guiEvent=guiEvent)
|
|
||||||
self.key = key
|
self.key = key
|
||||||
|
# super-init deferred to the end: callback errors if called before
|
||||||
|
LocationEvent.__init__(self, name, canvas, x, y, guiEvent=guiEvent)
|
||||||
|
|
||||||
|
|
||||||
def _get_renderer(figure, print_method, *, draw_disabled=False):
|
def _get_renderer(figure, print_method):
|
||||||
"""
|
"""
|
||||||
Get the renderer that would be used to save a `~.Figure`, and cache it on
|
Get the renderer that would be used to save a `~.Figure`, and cache it on
|
||||||
the figure.
|
the figure.
|
||||||
|
|
||||||
If *draw_disabled* is True, additionally replace draw_foo methods on
|
If you need a renderer without any active draw methods use
|
||||||
*renderer* by no-ops. This is used by the tight-bbox-saving renderer,
|
renderer._draw_disabled to temporary patch them out at your call site.
|
||||||
which needs to walk through the artist tree to compute the tight-bbox, but
|
|
||||||
for which the output file may be closed early.
|
|
||||||
"""
|
"""
|
||||||
# This is implemented by triggering a draw, then immediately jumping out of
|
# This is implemented by triggering a draw, then immediately jumping out of
|
||||||
# Figure.draw() by raising an exception.
|
# Figure.draw() by raising an exception.
|
||||||
|
@ -1540,11 +1561,6 @@ def _get_renderer(figure, print_method, *, draw_disabled=False):
|
||||||
except Done as exc:
|
except Done as exc:
|
||||||
renderer, = figure._cachedRenderer, = exc.args
|
renderer, = figure._cachedRenderer, = exc.args
|
||||||
|
|
||||||
if draw_disabled:
|
|
||||||
for meth_name in dir(RendererBase):
|
|
||||||
if meth_name.startswith("draw_"):
|
|
||||||
setattr(renderer, meth_name, lambda *args, **kwargs: None)
|
|
||||||
|
|
||||||
return renderer
|
return renderer
|
||||||
|
|
||||||
|
|
||||||
|
@ -2052,8 +2068,9 @@ default: :rc:`savefig.bbox`
|
||||||
# Some code (e.g. Figure.show) differentiates between having *no*
|
# Some code (e.g. Figure.show) differentiates between having *no*
|
||||||
# manager and a *None* manager, which should be fixed at some point,
|
# manager and a *None* manager, which should be fixed at some point,
|
||||||
# but this should be fine.
|
# but this should be fine.
|
||||||
with cbook._setattr_cm(self, _is_saving=True, manager=None), \
|
with cbook._setattr_cm(self, manager=None), \
|
||||||
cbook._setattr_cm(self.figure, dpi=dpi):
|
cbook._setattr_cm(self.figure, dpi=dpi), \
|
||||||
|
cbook._setattr_cm(canvas, _is_saving=True):
|
||||||
|
|
||||||
if facecolor is None:
|
if facecolor is None:
|
||||||
facecolor = rcParams['savefig.facecolor']
|
facecolor = rcParams['savefig.facecolor']
|
||||||
|
@ -2074,9 +2091,13 @@ default: :rc:`savefig.bbox`
|
||||||
renderer = _get_renderer(
|
renderer = _get_renderer(
|
||||||
self.figure,
|
self.figure,
|
||||||
functools.partial(
|
functools.partial(
|
||||||
print_method, dpi=dpi, orientation=orientation),
|
print_method, dpi=dpi, orientation=orientation)
|
||||||
draw_disabled=True)
|
)
|
||||||
self.figure.draw(renderer)
|
ctx = (renderer._draw_disabled()
|
||||||
|
if hasattr(renderer, '_draw_disabled')
|
||||||
|
else suppress())
|
||||||
|
with ctx:
|
||||||
|
self.figure.draw(renderer)
|
||||||
bbox_artists = kwargs.pop("bbox_extra_artists", None)
|
bbox_artists = kwargs.pop("bbox_extra_artists", None)
|
||||||
bbox_inches = self.figure.get_tightbbox(renderer,
|
bbox_inches = self.figure.get_tightbbox(renderer,
|
||||||
bbox_extra_artists=bbox_artists)
|
bbox_extra_artists=bbox_artists)
|
||||||
|
@ -2272,7 +2293,7 @@ default: :rc:`savefig.bbox`
|
||||||
The event loop blocks until a callback function triggers
|
The event loop blocks until a callback function triggers
|
||||||
`stop_event_loop`, or *timeout* is reached.
|
`stop_event_loop`, or *timeout* is reached.
|
||||||
|
|
||||||
If *timeout* is negative, never timeout.
|
If *timeout* is 0 or negative, never timeout.
|
||||||
|
|
||||||
Only interactive backends need to reimplement this method and it relies
|
Only interactive backends need to reimplement this method and it relies
|
||||||
on `flush_events` being properly implemented.
|
on `flush_events` being properly implemented.
|
||||||
|
|
|
@ -460,10 +460,18 @@ class FigureManagerTk(FigureManagerBase):
|
||||||
return toolmanager
|
return toolmanager
|
||||||
|
|
||||||
def resize(self, width, height):
|
def resize(self, width, height):
|
||||||
self.canvas._tkcanvas.master.geometry("%dx%d" % (width, height))
|
max_size = 1_400_000 # the measured max on xorg 1.20.8 was 1_409_023
|
||||||
|
|
||||||
if self.toolbar is not None:
|
if (width > max_size or height > max_size) and sys.platform == 'linux':
|
||||||
self.toolbar.configure(width=width)
|
raise ValueError(
|
||||||
|
'You have requested to resize the '
|
||||||
|
f'Tk window to ({width}, {height}), one of which '
|
||||||
|
f'is bigger than {max_size}. At larger sizes xorg will '
|
||||||
|
'either exit with an error on newer versions (~1.20) or '
|
||||||
|
'cause corruption on older version (~1.19). We '
|
||||||
|
'do not expect a window over a million pixel wide or tall '
|
||||||
|
'to be intended behavior.')
|
||||||
|
self.canvas._tkcanvas.configure(width=width, height=height)
|
||||||
|
|
||||||
def show(self):
|
def show(self):
|
||||||
with _restore_foreground_window_at_end():
|
with _restore_foreground_window_at_end():
|
||||||
|
@ -541,8 +549,12 @@ class NavigationToolbar2Tk(NavigationToolbar2, tk.Frame):
|
||||||
|
|
||||||
def set_cursor(self, cursor):
|
def set_cursor(self, cursor):
|
||||||
window = self.canvas.get_tk_widget().master
|
window = self.canvas.get_tk_widget().master
|
||||||
window.configure(cursor=cursord[cursor])
|
try:
|
||||||
window.update_idletasks()
|
window.configure(cursor=cursord[cursor])
|
||||||
|
except tkinter.TclError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
window.update_idletasks()
|
||||||
|
|
||||||
def _Button(self, text, file, command, extension='.gif'):
|
def _Button(self, text, file, command, extension='.gif'):
|
||||||
img_file = str(cbook._get_data_path('images', file + extension))
|
img_file = str(cbook._get_data_path('images', file + extension))
|
||||||
|
|
|
@ -1394,7 +1394,7 @@ end"""
|
||||||
streamarr['points'] = (flat_points - points_min) * factor
|
streamarr['points'] = (flat_points - points_min) * factor
|
||||||
streamarr['colors'] = flat_colors[:, :colordim] * 255.0
|
streamarr['colors'] = flat_colors[:, :colordim] * 255.0
|
||||||
|
|
||||||
self.write(streamarr.tostring())
|
self.write(streamarr.tobytes())
|
||||||
self.endStream()
|
self.endStream()
|
||||||
self.writeObject(self.gouraudObject, gouraudDict)
|
self.writeObject(self.gouraudObject, gouraudDict)
|
||||||
|
|
||||||
|
@ -1487,7 +1487,7 @@ end"""
|
||||||
if png:
|
if png:
|
||||||
self._writePng(data)
|
self._writePng(data)
|
||||||
else:
|
else:
|
||||||
self.currentstream.write(data.tostring())
|
self.currentstream.write(data.tobytes())
|
||||||
self.endStream()
|
self.endStream()
|
||||||
|
|
||||||
def writeImages(self):
|
def writeImages(self):
|
||||||
|
|
|
@ -543,8 +543,7 @@ translate
|
||||||
r'\psfrag{%s}[Bl][Bl][1][%f]{\fontsize{%f}{%f}%s}' % (
|
r'\psfrag{%s}[Bl][Bl][1][%f]{\fontsize{%f}{%f}%s}' % (
|
||||||
thetext, angle, fontsize, fontsize*1.25, tex))
|
thetext, angle, fontsize, fontsize*1.25, tex))
|
||||||
else:
|
else:
|
||||||
# Stick to the bottom alignment, but this may give incorrect
|
# Stick to the bottom alignment.
|
||||||
# baseline some times.
|
|
||||||
pos = _nums_to_str(x-corr, y-bl)
|
pos = _nums_to_str(x-corr, y-bl)
|
||||||
self.psfrag.append(
|
self.psfrag.append(
|
||||||
r'\psfrag{%s}[bl][bl][1][%f]{\fontsize{%f}{%f}%s}' % (
|
r'\psfrag{%s}[bl][bl][1][%f]{\fontsize{%f}{%f}%s}' % (
|
||||||
|
@ -694,7 +693,7 @@ grestore
|
||||||
streamarr['points'] = (flat_points - points_min) * factor
|
streamarr['points'] = (flat_points - points_min) * factor
|
||||||
streamarr['colors'] = flat_colors[:, :3] * 255.0
|
streamarr['colors'] = flat_colors[:, :3] * 255.0
|
||||||
|
|
||||||
stream = quote_ps_string(streamarr.tostring())
|
stream = quote_ps_string(streamarr.tobytes())
|
||||||
|
|
||||||
self._pswriter.write(f"""\
|
self._pswriter.write(f"""\
|
||||||
gsave
|
gsave
|
||||||
|
@ -1234,19 +1233,21 @@ def convert_psfrags(tmpfile, psfrags, font_preamble, custom_preamble,
|
||||||
"""
|
"""
|
||||||
with mpl.rc_context({
|
with mpl.rc_context({
|
||||||
"text.latex.preamble":
|
"text.latex.preamble":
|
||||||
rcParams["text.latex.preamble"] +
|
mpl.rcParams["text.latex.preamble"] +
|
||||||
r"\usepackage{psfrag,color}"
|
r"\usepackage{psfrag,color}""\n"
|
||||||
r"\usepackage[dvips]{graphicx}"
|
r"\usepackage[dvips]{graphicx}""\n"
|
||||||
r"\PassOptionsToPackage{dvips}{geometry}"}):
|
r"\geometry{papersize={%(width)sin,%(height)sin},"
|
||||||
|
r"body={%(width)sin,%(height)sin},margin=0in}"
|
||||||
|
% {"width": paper_width, "height": paper_height}
|
||||||
|
}):
|
||||||
dvifile = TexManager().make_dvi(
|
dvifile = TexManager().make_dvi(
|
||||||
r"\newgeometry{papersize={%(width)sin,%(height)sin},"
|
"\n"
|
||||||
r"body={%(width)sin,%(height)sin}, margin={0in,0in}}""\n"
|
r"\begin{figure}""\n"
|
||||||
r"\begin{figure}"
|
r" \centering\leavevmode""\n"
|
||||||
r"\centering\leavevmode%(psfrags)s"
|
r" %(psfrags)s""\n"
|
||||||
r"\includegraphics*[angle=%(angle)s]{%(epsfile)s}"
|
r" \includegraphics*[angle=%(angle)s]{%(epsfile)s}""\n"
|
||||||
r"\end{figure}"
|
r"\end{figure}"
|
||||||
% {
|
% {
|
||||||
"width": paper_width, "height": paper_height,
|
|
||||||
"psfrags": "\n".join(psfrags),
|
"psfrags": "\n".join(psfrags),
|
||||||
"angle": 90 if orientation == 'landscape' else 0,
|
"angle": 90 if orientation == 'landscape' else 0,
|
||||||
"epsfile": pathlib.Path(tmpfile).resolve().as_posix(),
|
"epsfile": pathlib.Path(tmpfile).resolve().as_posix(),
|
||||||
|
|
|
@ -15,10 +15,12 @@ from matplotlib.backend_bases import (
|
||||||
import matplotlib.backends.qt_editor.figureoptions as figureoptions
|
import matplotlib.backends.qt_editor.figureoptions as figureoptions
|
||||||
from matplotlib.backends.qt_editor.formsubplottool import UiSubplotTool
|
from matplotlib.backends.qt_editor.formsubplottool import UiSubplotTool
|
||||||
from matplotlib.backend_managers import ToolManager
|
from matplotlib.backend_managers import ToolManager
|
||||||
|
from . import qt_compat
|
||||||
from .qt_compat import (
|
from .qt_compat import (
|
||||||
QtCore, QtGui, QtWidgets, _isdeleted, _getSaveFileName,
|
QtCore, QtGui, QtWidgets, _isdeleted, _getSaveFileName,
|
||||||
is_pyqt5, __version__, QT_API)
|
is_pyqt5, __version__, QT_API, _setDevicePixelRatioF,
|
||||||
|
_devicePixelRatioF)
|
||||||
|
|
||||||
|
|
||||||
backend_version = __version__
|
backend_version = __version__
|
||||||
|
|
||||||
|
@ -267,12 +269,7 @@ class FigureCanvasQT(QtWidgets.QWidget, FigureCanvasBase):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _dpi_ratio(self):
|
def _dpi_ratio(self):
|
||||||
# Not available on Qt4 or some older Qt5.
|
return _devicePixelRatioF(self)
|
||||||
try:
|
|
||||||
# self.devicePixelRatio() returns 0 in rare cases
|
|
||||||
return self.devicePixelRatio() or 1
|
|
||||||
except AttributeError:
|
|
||||||
return 1
|
|
||||||
|
|
||||||
def _update_dpi(self):
|
def _update_dpi(self):
|
||||||
# As described in __init__ above, we need to be careful in cases with
|
# As described in __init__ above, we need to be careful in cases with
|
||||||
|
@ -454,8 +451,9 @@ class FigureCanvasQT(QtWidgets.QWidget, FigureCanvasBase):
|
||||||
if hasattr(self, "_event_loop") and self._event_loop.isRunning():
|
if hasattr(self, "_event_loop") and self._event_loop.isRunning():
|
||||||
raise RuntimeError("Event loop already running")
|
raise RuntimeError("Event loop already running")
|
||||||
self._event_loop = event_loop = QtCore.QEventLoop()
|
self._event_loop = event_loop = QtCore.QEventLoop()
|
||||||
if timeout:
|
if timeout > 0:
|
||||||
timer = QtCore.QTimer.singleShot(timeout * 1000, event_loop.quit)
|
timer = QtCore.QTimer.singleShot(int(timeout * 1000),
|
||||||
|
event_loop.quit)
|
||||||
event_loop.exec_()
|
event_loop.exec_()
|
||||||
|
|
||||||
def stop_event_loop(self, event=None):
|
def stop_event_loop(self, event=None):
|
||||||
|
@ -508,7 +506,7 @@ class FigureCanvasQT(QtWidgets.QWidget, FigureCanvasBase):
|
||||||
pen = QtGui.QPen(QtCore.Qt.black, 1 / self._dpi_ratio,
|
pen = QtGui.QPen(QtCore.Qt.black, 1 / self._dpi_ratio,
|
||||||
QtCore.Qt.DotLine)
|
QtCore.Qt.DotLine)
|
||||||
painter.setPen(pen)
|
painter.setPen(pen)
|
||||||
painter.drawRect(*(pt / self._dpi_ratio for pt in rect))
|
painter.drawRect(*(int(pt / self._dpi_ratio) for pt in rect))
|
||||||
else:
|
else:
|
||||||
def _draw_rect_callback(painter):
|
def _draw_rect_callback(painter):
|
||||||
return
|
return
|
||||||
|
@ -683,8 +681,7 @@ class NavigationToolbar2QT(NavigationToolbar2, QtWidgets.QToolBar):
|
||||||
if is_pyqt5():
|
if is_pyqt5():
|
||||||
name = name.replace('.png', '_large.png')
|
name = name.replace('.png', '_large.png')
|
||||||
pm = QtGui.QPixmap(os.path.join(self.basedir, name))
|
pm = QtGui.QPixmap(os.path.join(self.basedir, name))
|
||||||
if hasattr(pm, 'setDevicePixelRatio'):
|
_setDevicePixelRatioF(pm, _devicePixelRatioF(self))
|
||||||
pm.setDevicePixelRatio(self.canvas._dpi_ratio)
|
|
||||||
if color is not None:
|
if color is not None:
|
||||||
mask = pm.createMaskFromColor(QtGui.QColor('black'),
|
mask = pm.createMaskFromColor(QtGui.QColor('black'),
|
||||||
QtCore.Qt.MaskOutColor)
|
QtCore.Qt.MaskOutColor)
|
||||||
|
|
|
@ -11,7 +11,7 @@ from .backend_agg import FigureCanvasAgg
|
||||||
from .backend_qt5 import (
|
from .backend_qt5 import (
|
||||||
QtCore, QtGui, QtWidgets, _BackendQT5, FigureCanvasQT, FigureManagerQT,
|
QtCore, QtGui, QtWidgets, _BackendQT5, FigureCanvasQT, FigureManagerQT,
|
||||||
NavigationToolbar2QT, backend_version)
|
NavigationToolbar2QT, backend_version)
|
||||||
from .qt_compat import QT_API
|
from .qt_compat import QT_API, _setDevicePixelRatioF
|
||||||
|
|
||||||
|
|
||||||
class FigureCanvasQTAgg(FigureCanvasAgg, FigureCanvasQT):
|
class FigureCanvasQTAgg(FigureCanvasAgg, FigureCanvasQT):
|
||||||
|
@ -38,45 +38,44 @@ class FigureCanvasQTAgg(FigureCanvasAgg, FigureCanvasQT):
|
||||||
return
|
return
|
||||||
|
|
||||||
painter = QtGui.QPainter(self)
|
painter = QtGui.QPainter(self)
|
||||||
|
try:
|
||||||
|
# See documentation of QRect: bottom() and right() are off
|
||||||
|
# by 1, so use left() + width() and top() + height().
|
||||||
|
rect = event.rect()
|
||||||
|
# scale rect dimensions using the screen dpi ratio to get
|
||||||
|
# correct values for the Figure coordinates (rather than
|
||||||
|
# QT5's coords)
|
||||||
|
width = rect.width() * self._dpi_ratio
|
||||||
|
height = rect.height() * self._dpi_ratio
|
||||||
|
left, top = self.mouseEventCoords(rect.topLeft())
|
||||||
|
# shift the "top" by the height of the image to get the
|
||||||
|
# correct corner for our coordinate system
|
||||||
|
bottom = top - height
|
||||||
|
# same with the right side of the image
|
||||||
|
right = left + width
|
||||||
|
# create a buffer using the image bounding box
|
||||||
|
bbox = Bbox([[left, bottom], [right, top]])
|
||||||
|
reg = self.copy_from_bbox(bbox)
|
||||||
|
buf = cbook._unmultiplied_rgba8888_to_premultiplied_argb32(
|
||||||
|
memoryview(reg))
|
||||||
|
|
||||||
# See documentation of QRect: bottom() and right() are off by 1, so use
|
# clear the widget canvas
|
||||||
# left() + width() and top() + height().
|
painter.eraseRect(rect)
|
||||||
rect = event.rect()
|
|
||||||
# scale rect dimensions using the screen dpi ratio to get
|
|
||||||
# correct values for the Figure coordinates (rather than QT5's coords)
|
|
||||||
width = rect.width() * self._dpi_ratio
|
|
||||||
height = rect.height() * self._dpi_ratio
|
|
||||||
left, top = self.mouseEventCoords(rect.topLeft())
|
|
||||||
# shift the "top" by the height of the image to get the
|
|
||||||
# correct corner for our coordinate system
|
|
||||||
bottom = top - height
|
|
||||||
# same with the right side of the image
|
|
||||||
right = left + width
|
|
||||||
# create a buffer using the image bounding box
|
|
||||||
bbox = Bbox([[left, bottom], [right, top]])
|
|
||||||
reg = self.copy_from_bbox(bbox)
|
|
||||||
buf = cbook._unmultiplied_rgba8888_to_premultiplied_argb32(
|
|
||||||
memoryview(reg))
|
|
||||||
|
|
||||||
# clear the widget canvas
|
qimage = QtGui.QImage(buf, buf.shape[1], buf.shape[0],
|
||||||
painter.eraseRect(rect)
|
QtGui.QImage.Format_ARGB32_Premultiplied)
|
||||||
|
_setDevicePixelRatioF(qimage, self._dpi_ratio)
|
||||||
|
# set origin using original QT coordinates
|
||||||
|
origin = QtCore.QPoint(rect.left(), rect.top())
|
||||||
|
painter.drawImage(origin, qimage)
|
||||||
|
# Adjust the buf reference count to work around a memory
|
||||||
|
# leak bug in QImage under PySide on Python 3.
|
||||||
|
if QT_API in ('PySide', 'PySide2'):
|
||||||
|
ctypes.c_long.from_address(id(buf)).value = 1
|
||||||
|
|
||||||
qimage = QtGui.QImage(buf, buf.shape[1], buf.shape[0],
|
self._draw_rect_callback(painter)
|
||||||
QtGui.QImage.Format_ARGB32_Premultiplied)
|
finally:
|
||||||
if hasattr(qimage, 'setDevicePixelRatio'):
|
painter.end()
|
||||||
# Not available on Qt4 or some older Qt5.
|
|
||||||
qimage.setDevicePixelRatio(self._dpi_ratio)
|
|
||||||
# set origin using original QT coordinates
|
|
||||||
origin = QtCore.QPoint(rect.left(), rect.top())
|
|
||||||
painter.drawImage(origin, qimage)
|
|
||||||
# Adjust the buf reference count to work around a memory
|
|
||||||
# leak bug in QImage under PySide on Python 3.
|
|
||||||
if QT_API in ('PySide', 'PySide2'):
|
|
||||||
ctypes.c_long.from_address(id(buf)).value = 1
|
|
||||||
|
|
||||||
self._draw_rect_callback(painter)
|
|
||||||
|
|
||||||
painter.end()
|
|
||||||
|
|
||||||
def blit(self, bbox=None):
|
def blit(self, bbox=None):
|
||||||
# docstring inherited
|
# docstring inherited
|
||||||
|
@ -86,7 +85,7 @@ class FigureCanvasQTAgg(FigureCanvasAgg, FigureCanvasQT):
|
||||||
bbox = self.figure.bbox
|
bbox = self.figure.bbox
|
||||||
|
|
||||||
# repaint uses logical pixels, not physical pixels like the renderer.
|
# repaint uses logical pixels, not physical pixels like the renderer.
|
||||||
l, b, w, h = [pt / self._dpi_ratio for pt in bbox.bounds]
|
l, b, w, h = [int(pt / self._dpi_ratio) for pt in bbox.bounds]
|
||||||
t = b + h
|
t = b + h
|
||||||
self.repaint(l, self.renderer.height / self._dpi_ratio - t, w, h)
|
self.repaint(l, self.renderer.height / self._dpi_ratio - t, w, h)
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import ctypes
|
||||||
|
|
||||||
from .backend_cairo import cairo, FigureCanvasCairo, RendererCairo
|
from .backend_cairo import cairo, FigureCanvasCairo, RendererCairo
|
||||||
from .backend_qt5 import QtCore, QtGui, _BackendQT5, FigureCanvasQT
|
from .backend_qt5 import QtCore, QtGui, _BackendQT5, FigureCanvasQT
|
||||||
from .qt_compat import QT_API
|
from .qt_compat import QT_API, _setDevicePixelRatioF
|
||||||
|
|
||||||
|
|
||||||
class FigureCanvasQTCairo(FigureCanvasQT, FigureCanvasCairo):
|
class FigureCanvasQTCairo(FigureCanvasQT, FigureCanvasCairo):
|
||||||
|
@ -19,8 +19,8 @@ class FigureCanvasQTCairo(FigureCanvasQT, FigureCanvasCairo):
|
||||||
def paintEvent(self, event):
|
def paintEvent(self, event):
|
||||||
self._update_dpi()
|
self._update_dpi()
|
||||||
dpi_ratio = self._dpi_ratio
|
dpi_ratio = self._dpi_ratio
|
||||||
width = dpi_ratio * self.width()
|
width = int(dpi_ratio * self.width())
|
||||||
height = dpi_ratio * self.height()
|
height = int(dpi_ratio * self.height())
|
||||||
if (width, height) != self._renderer.get_canvas_width_height():
|
if (width, height) != self._renderer.get_canvas_width_height():
|
||||||
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
|
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
|
||||||
self._renderer.set_ctx_from_surface(surface)
|
self._renderer.set_ctx_from_surface(surface)
|
||||||
|
@ -33,9 +33,7 @@ class FigureCanvasQTCairo(FigureCanvasQT, FigureCanvasCairo):
|
||||||
# QImage under PySide on Python 3.
|
# QImage under PySide on Python 3.
|
||||||
if QT_API == 'PySide':
|
if QT_API == 'PySide':
|
||||||
ctypes.c_long.from_address(id(buf)).value = 1
|
ctypes.c_long.from_address(id(buf)).value = 1
|
||||||
if hasattr(qimage, 'setDevicePixelRatio'):
|
_setDevicePixelRatioF(qimage, dpi_ratio)
|
||||||
# Not available on Qt4 or some older Qt5.
|
|
||||||
qimage.setDevicePixelRatio(dpi_ratio)
|
|
||||||
painter = QtGui.QPainter(self)
|
painter = QtGui.QPainter(self)
|
||||||
painter.eraseRect(event.rect())
|
painter.eraseRect(event.rect())
|
||||||
painter.drawImage(0, 0, qimage)
|
painter.drawImage(0, 0, qimage)
|
||||||
|
|
|
@ -288,7 +288,7 @@ class RendererWx(RendererBase):
|
||||||
w = self.width
|
w = self.width
|
||||||
h = self.height
|
h = self.height
|
||||||
rows, cols = im.shape[:2]
|
rows, cols = im.shape[:2]
|
||||||
bitmap = wx.Bitmap.FromBufferRGBA(cols, rows, im.tostring())
|
bitmap = wx.Bitmap.FromBufferRGBA(cols, rows, im.tobytes())
|
||||||
gc = self.get_gc()
|
gc = self.get_gc()
|
||||||
gc.select()
|
gc.select()
|
||||||
gc.gfx_ctx.DrawBitmap(bitmap, int(l), int(self.height - b),
|
gc.gfx_ctx.DrawBitmap(bitmap, int(l), int(self.height - b),
|
||||||
|
@ -702,7 +702,9 @@ class _FigureCanvasWxBase(FigureCanvasBase, wx.Panel):
|
||||||
The 'WXAgg' backend sets origin accordingly.
|
The 'WXAgg' backend sets origin accordingly.
|
||||||
"""
|
"""
|
||||||
DEBUG_MSG("gui_repaint()", 1, self)
|
DEBUG_MSG("gui_repaint()", 1, self)
|
||||||
if self.IsShownOnScreen():
|
# The "if self" check avoids a "wrapped C/C++ object has been deleted"
|
||||||
|
# RuntimeError if doing things after window is closed.
|
||||||
|
if self and self.IsShownOnScreen():
|
||||||
if not drawDC:
|
if not drawDC:
|
||||||
# not called from OnPaint use a ClientDC
|
# not called from OnPaint use a ClientDC
|
||||||
drawDC = wx.ClientDC(self)
|
drawDC = wx.ClientDC(self)
|
||||||
|
@ -776,14 +778,14 @@ class _FigureCanvasWxBase(FigureCanvasBase, wx.Panel):
|
||||||
# no change in size
|
# no change in size
|
||||||
return
|
return
|
||||||
self._width, self._height = size
|
self._width, self._height = size
|
||||||
# Create a new, correctly sized bitmap
|
|
||||||
self.bitmap = wx.Bitmap(self._width, self._height)
|
|
||||||
|
|
||||||
self._isDrawn = False
|
self._isDrawn = False
|
||||||
|
|
||||||
if self._width <= 1 or self._height <= 1:
|
if self._width <= 1 or self._height <= 1:
|
||||||
return # Empty figure
|
return # Empty figure
|
||||||
|
|
||||||
|
# Create a new, correctly sized bitmap
|
||||||
|
self.bitmap = wx.Bitmap(self._width, self._height)
|
||||||
|
|
||||||
dpival = self.figure.dpi
|
dpival = self.figure.dpi
|
||||||
winch = self._width / dpival
|
winch = self._width / dpival
|
||||||
hinch = self._height / dpival
|
hinch = self._height / dpival
|
||||||
|
@ -978,14 +980,11 @@ class FigureCanvasWx(_FigureCanvasWxBase):
|
||||||
|
|
||||||
# Now that we have rendered into the bitmap, save it to the appropriate
|
# Now that we have rendered into the bitmap, save it to the appropriate
|
||||||
# file type and clean up.
|
# file type and clean up.
|
||||||
if isinstance(filename, str):
|
if (cbook.is_writable_file_like(filename) and
|
||||||
if not image.SaveFile(filename, filetype):
|
not isinstance(image, wx.Image)):
|
||||||
raise RuntimeError(f'Could not save figure to {filename}')
|
image = image.ConvertToImage()
|
||||||
elif cbook.is_writable_file_like(filename):
|
if not image.SaveFile(filename, filetype):
|
||||||
if not isinstance(image, wx.Image):
|
raise RuntimeError(f'Could not save figure to {filename}')
|
||||||
image = image.ConvertToImage()
|
|
||||||
if not image.SaveStream(filename, filetype):
|
|
||||||
raise RuntimeError(f'Could not save figure to {filename}')
|
|
||||||
|
|
||||||
# Restore everything to normal
|
# Restore everything to normal
|
||||||
self.bitmap = origBitmap
|
self.bitmap = origBitmap
|
||||||
|
@ -997,7 +996,10 @@ class FigureCanvasWx(_FigureCanvasWxBase):
|
||||||
# otherwise.
|
# otherwise.
|
||||||
if self._isDrawn:
|
if self._isDrawn:
|
||||||
self.draw()
|
self.draw()
|
||||||
self.Refresh()
|
# The "if self" check avoids a "wrapped C/C++ object has been deleted"
|
||||||
|
# RuntimeError if doing things after window is closed.
|
||||||
|
if self:
|
||||||
|
self.Refresh()
|
||||||
|
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
|
@ -1501,7 +1503,7 @@ class NavigationToolbar2Wx(NavigationToolbar2, wx.ToolBar):
|
||||||
|
|
||||||
def set_message(self, s):
|
def set_message(self, s):
|
||||||
status_bar = self.GetTopLevelParent().GetStatusBar()
|
status_bar = self.GetTopLevelParent().GetStatusBar()
|
||||||
if status_bar is not None:
|
if status_bar is not None and hasattr(status_bar, 'set_function'):
|
||||||
status_bar.set_function(s)
|
status_bar.set_function(s)
|
||||||
|
|
||||||
def set_history_buttons(self):
|
def set_history_buttons(self):
|
||||||
|
|
|
@ -92,7 +92,7 @@ def _setup_pyqt4():
|
||||||
|
|
||||||
def _setup_pyqt4_internal(api):
|
def _setup_pyqt4_internal(api):
|
||||||
global QtCore, QtGui, QtWidgets, \
|
global QtCore, QtGui, QtWidgets, \
|
||||||
__version__, is_pyqt5, _getSaveFileName
|
__version__, is_pyqt5, _isdeleted, _getSaveFileName
|
||||||
# List of incompatible APIs:
|
# List of incompatible APIs:
|
||||||
# http://pyqt.sourceforge.net/Docs/PyQt4/incompatible_apis.html
|
# http://pyqt.sourceforge.net/Docs/PyQt4/incompatible_apis.html
|
||||||
_sip_apis = ["QDate", "QDateTime", "QString", "QTextStream", "QTime",
|
_sip_apis = ["QDate", "QDateTime", "QString", "QTextStream", "QTime",
|
||||||
|
@ -173,4 +173,38 @@ else: # We should not get there.
|
||||||
# These globals are only defined for backcompatibility purposes.
|
# These globals are only defined for backcompatibility purposes.
|
||||||
ETS = dict(pyqt=(QT_API_PYQTv2, 4), pyside=(QT_API_PYSIDE, 4),
|
ETS = dict(pyqt=(QT_API_PYQTv2, 4), pyside=(QT_API_PYSIDE, 4),
|
||||||
pyqt5=(QT_API_PYQT5, 5), pyside2=(QT_API_PYSIDE2, 5))
|
pyqt5=(QT_API_PYQT5, 5), pyside2=(QT_API_PYSIDE2, 5))
|
||||||
QT_RC_MAJOR_VERSION = 5 if is_pyqt5() else 4
|
|
||||||
|
QT_RC_MAJOR_VERSION = int(QtCore.qVersion().split(".")[0])
|
||||||
|
|
||||||
|
|
||||||
|
def _devicePixelRatioF(obj):
|
||||||
|
"""
|
||||||
|
Return obj.devicePixelRatioF() with graceful fallback for older Qt.
|
||||||
|
|
||||||
|
This can be replaced by the direct call when we require Qt>=5.6.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# Not available on Qt<5.6
|
||||||
|
return obj.devicePixelRatioF() or 1
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
# Not available on Qt4 or some older Qt5.
|
||||||
|
# self.devicePixelRatio() returns 0 in rare cases
|
||||||
|
return obj.devicePixelRatio() or 1
|
||||||
|
except AttributeError:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
def _setDevicePixelRatioF(obj, val):
|
||||||
|
"""
|
||||||
|
Call obj.setDevicePixelRatioF(val) with graceful fallback for older Qt.
|
||||||
|
|
||||||
|
This can be replaced by the direct call when we require Qt>=5.6.
|
||||||
|
"""
|
||||||
|
if hasattr(obj, 'setDevicePixelRatioF'):
|
||||||
|
# Not available on Qt<5.6
|
||||||
|
obj.setDevicePixelRatioF(val)
|
||||||
|
elif hasattr(obj, 'setDevicePixelRatio'):
|
||||||
|
# Not available on Qt4 or some older Qt5.
|
||||||
|
obj.setDevicePixelRatio(val)
|
||||||
|
|
|
@ -184,7 +184,7 @@ def deprecated(since, *, message='', name='', alternative='', pending=False,
|
||||||
obj.__doc__ = new_doc
|
obj.__doc__ = new_doc
|
||||||
except AttributeError: # Can't set on some extension objects.
|
except AttributeError: # Can't set on some extension objects.
|
||||||
pass
|
pass
|
||||||
obj.__init__ = wrapper
|
obj.__init__ = functools.wraps(obj.__init__)(wrapper)
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
elif isinstance(obj, property):
|
elif isinstance(obj, property):
|
||||||
|
|
|
@ -213,32 +213,31 @@ class Collection(artist.Artist, cm.ScalarMappable):
|
||||||
# we may have transform.contains_branch(transData) but not
|
# we may have transform.contains_branch(transData) but not
|
||||||
# transforms.get_affine().contains_branch(transData). But later,
|
# transforms.get_affine().contains_branch(transData). But later,
|
||||||
# be careful to only apply the affine part that remains.
|
# be careful to only apply the affine part that remains.
|
||||||
if not transOffset.is_affine:
|
|
||||||
offsets = transOffset.transform_non_affine(offsets)
|
|
||||||
|
|
||||||
if isinstance(offsets, np.ma.MaskedArray):
|
if isinstance(offsets, np.ma.MaskedArray):
|
||||||
offsets = offsets.filled(np.nan)
|
offsets = offsets.filled(np.nan)
|
||||||
# get_path_collection_extents handles nan but not masked arrays
|
# get_path_collection_extents handles nan but not masked arrays
|
||||||
|
|
||||||
if len(paths) and len(offsets):
|
if len(paths) and len(offsets):
|
||||||
if transform.contains_branch(transData):
|
if any(transform.contains_branch_seperately(transData)):
|
||||||
# collections that are just in data units (like quiver)
|
# collections that are just in data units (like quiver)
|
||||||
# can properly have the axes limits set by their shape +
|
# can properly have the axes limits set by their shape +
|
||||||
# offset. LineCollections that have no offsets can
|
# offset. LineCollections that have no offsets can
|
||||||
# also use this algorithm (like streamplot).
|
# also use this algorithm (like streamplot).
|
||||||
result = mpath.get_path_collection_extents(
|
result = mpath.get_path_collection_extents(
|
||||||
transform.get_affine(), paths, self.get_transforms(),
|
transform.get_affine(), paths, self.get_transforms(),
|
||||||
offsets, transOffset.get_affine().frozen())
|
transOffset.transform_non_affine(offsets),
|
||||||
return result.inverse_transformed(transData)
|
transOffset.get_affine().frozen())
|
||||||
|
return result.transformed(transData.inverted())
|
||||||
if not self._offsetsNone:
|
if not self._offsetsNone:
|
||||||
# this is for collections that have their paths (shapes)
|
# this is for collections that have their paths (shapes)
|
||||||
# in physical, axes-relative, or figure-relative units
|
# in physical, axes-relative, or figure-relative units
|
||||||
# (i.e. like scatter). We can't uniquely set limits based on
|
# (i.e. like scatter). We can't uniquely set limits based on
|
||||||
# those shapes, so we just set the limits based on their
|
# those shapes, so we just set the limits based on their
|
||||||
# location.
|
# location.
|
||||||
# Finish the transform:
|
|
||||||
offsets = (transOffset.get_affine() +
|
offsets = (transOffset - transData).transform(offsets)
|
||||||
transData.inverted()).transform(offsets)
|
# note A-B means A B^{-1}
|
||||||
offsets = np.ma.masked_invalid(offsets)
|
offsets = np.ma.masked_invalid(offsets)
|
||||||
if not offsets.mask.all():
|
if not offsets.mask.all():
|
||||||
points = np.row_stack((offsets.min(axis=0),
|
points = np.row_stack((offsets.min(axis=0),
|
||||||
|
|
|
@ -405,7 +405,7 @@ class ColorbarBase(_ColorbarMappableDummy):
|
||||||
|
|
||||||
ticklocation : {'auto', 'left', 'right', 'top', 'bottom'}
|
ticklocation : {'auto', 'left', 'right', 'top', 'bottom'}
|
||||||
|
|
||||||
extend : {'neiter', 'both', 'min', 'max'}
|
extend : {'neither', 'both', 'min', 'max'}
|
||||||
|
|
||||||
spacing : {'uniform', 'proportional'}
|
spacing : {'uniform', 'proportional'}
|
||||||
|
|
||||||
|
|
|
@ -1713,7 +1713,7 @@ class LightSource:
|
||||||
completely in shadow and 1 is completely illuminated.
|
completely in shadow and 1 is completely illuminated.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Because most image and raster gis data has the first row in the array
|
# Because most image and raster GIS data has the first row in the array
|
||||||
# as the "top" of the image, dy is implicitly negative. This is
|
# as the "top" of the image, dy is implicitly negative. This is
|
||||||
# consistent to what `imshow` assumes, as well.
|
# consistent to what `imshow` assumes, as well.
|
||||||
dy = -dy
|
dy = -dy
|
||||||
|
|
|
@ -269,6 +269,12 @@ class Dvi:
|
||||||
maxx = max(maxx, x + w)
|
maxx = max(maxx, x + w)
|
||||||
maxy = max(maxy, y + e)
|
maxy = max(maxy, y + e)
|
||||||
maxy_pure = max(maxy_pure, y)
|
maxy_pure = max(maxy_pure, y)
|
||||||
|
if self._baseline_v is not None:
|
||||||
|
maxy_pure = self._baseline_v # This should normally be the case.
|
||||||
|
self._baseline_v = None
|
||||||
|
|
||||||
|
if not self.text and not self.boxes: # Avoid infs/nans from inf+/-inf.
|
||||||
|
return Page(text=[], boxes=[], width=0, height=0, descent=0)
|
||||||
|
|
||||||
if self.dpi is None:
|
if self.dpi is None:
|
||||||
# special case for ease of debugging: output raw dvi coordinates
|
# special case for ease of debugging: output raw dvi coordinates
|
||||||
|
@ -296,9 +302,24 @@ class Dvi:
|
||||||
Read one page from the file. Return True if successful,
|
Read one page from the file. Return True if successful,
|
||||||
False if there were no more pages.
|
False if there were no more pages.
|
||||||
"""
|
"""
|
||||||
|
# Pages appear to start with the sequence
|
||||||
|
# bop (begin of page)
|
||||||
|
# xxx comment
|
||||||
|
# down
|
||||||
|
# push
|
||||||
|
# down, down
|
||||||
|
# push
|
||||||
|
# down (possibly multiple)
|
||||||
|
# push <= here, v is the baseline position.
|
||||||
|
# etc.
|
||||||
|
# (dviasm is useful to explore this structure.)
|
||||||
|
self._baseline_v = None
|
||||||
while True:
|
while True:
|
||||||
byte = self.file.read(1)[0]
|
byte = self.file.read(1)[0]
|
||||||
self._dtable[byte](self, byte)
|
self._dtable[byte](self, byte)
|
||||||
|
if (self._baseline_v is None
|
||||||
|
and len(getattr(self, "stack", [])) == 3):
|
||||||
|
self._baseline_v = self.v
|
||||||
if byte == 140: # end of page
|
if byte == 140: # end of page
|
||||||
return True
|
return True
|
||||||
if self.state is _dvistate.post_post: # end of file
|
if self.state is _dvistate.post_post: # end of file
|
||||||
|
|
|
@ -2478,7 +2478,7 @@ default: 'top'
|
||||||
|
|
||||||
from .tight_layout import (
|
from .tight_layout import (
|
||||||
get_renderer, get_subplotspec_list, get_tight_layout_figure)
|
get_renderer, get_subplotspec_list, get_tight_layout_figure)
|
||||||
|
from contextlib import suppress
|
||||||
subplotspec_list = get_subplotspec_list(self.axes)
|
subplotspec_list = get_subplotspec_list(self.axes)
|
||||||
if None in subplotspec_list:
|
if None in subplotspec_list:
|
||||||
cbook._warn_external("This figure includes Axes that are not "
|
cbook._warn_external("This figure includes Axes that are not "
|
||||||
|
@ -2487,10 +2487,13 @@ default: 'top'
|
||||||
|
|
||||||
if renderer is None:
|
if renderer is None:
|
||||||
renderer = get_renderer(self)
|
renderer = get_renderer(self)
|
||||||
|
ctx = (renderer._draw_disabled()
|
||||||
kwargs = get_tight_layout_figure(
|
if hasattr(renderer, '_draw_disabled')
|
||||||
self, self.axes, subplotspec_list, renderer,
|
else suppress())
|
||||||
pad=pad, h_pad=h_pad, w_pad=w_pad, rect=rect)
|
with ctx:
|
||||||
|
kwargs = get_tight_layout_figure(
|
||||||
|
self, self.axes, subplotspec_list, renderer,
|
||||||
|
pad=pad, h_pad=h_pad, w_pad=w_pad, rect=rect)
|
||||||
if kwargs:
|
if kwargs:
|
||||||
self.subplots_adjust(**kwargs)
|
self.subplots_adjust(**kwargs)
|
||||||
|
|
||||||
|
|
|
@ -48,9 +48,9 @@ class GridSpecBase:
|
||||||
self.set_width_ratios(width_ratios)
|
self.set_width_ratios(width_ratios)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
height_arg = (', height_ratios=%r' % self._row_height_ratios
|
height_arg = (', height_ratios=%r' % (self._row_height_ratios,)
|
||||||
if self._row_height_ratios is not None else '')
|
if self._row_height_ratios is not None else '')
|
||||||
width_arg = (', width_ratios=%r' % self._col_width_ratios
|
width_arg = (', width_ratios=%r' % (self._col_width_ratios,)
|
||||||
if self._col_width_ratios is not None else '')
|
if self._col_width_ratios is not None else '')
|
||||||
return '{clsname}({nrows}, {ncols}{optionals})'.format(
|
return '{clsname}({nrows}, {ncols}{optionals})'.format(
|
||||||
clsname=self.__class__.__name__,
|
clsname=self.__class__.__name__,
|
||||||
|
|
|
@ -1592,14 +1592,12 @@ class Arc(Ellipse):
|
||||||
calculation much easier than doing rotated ellipse
|
calculation much easier than doing rotated ellipse
|
||||||
intersection directly).
|
intersection directly).
|
||||||
|
|
||||||
This uses the "line intersecting a circle" algorithm
|
This uses the "line intersecting a circle" algorithm from:
|
||||||
from:
|
|
||||||
|
|
||||||
Vince, John. *Geometry for Computer Graphics: Formulae,
|
Vince, John. *Geometry for Computer Graphics: Formulae,
|
||||||
Examples & Proofs.* London: Springer-Verlag, 2005.
|
Examples & Proofs.* London: Springer-Verlag, 2005.
|
||||||
|
|
||||||
2. The angles of each of the intersection points are
|
2. The angles of each of the intersection points are calculated.
|
||||||
calculated.
|
|
||||||
|
|
||||||
3. Proceeding counterclockwise starting in the positive
|
3. Proceeding counterclockwise starting in the positive
|
||||||
x-direction, each of the visible arc-segments between the
|
x-direction, each of the visible arc-segments between the
|
||||||
|
@ -1609,6 +1607,8 @@ class Arc(Ellipse):
|
||||||
"""
|
"""
|
||||||
if not hasattr(self, 'axes'):
|
if not hasattr(self, 'axes'):
|
||||||
raise RuntimeError('Arcs can only be used in Axes instances')
|
raise RuntimeError('Arcs can only be used in Axes instances')
|
||||||
|
if not self.get_visible():
|
||||||
|
return
|
||||||
|
|
||||||
self._recompute_transform()
|
self._recompute_transform()
|
||||||
|
|
||||||
|
@ -1621,44 +1621,62 @@ class Arc(Ellipse):
|
||||||
theta = np.deg2rad(theta)
|
theta = np.deg2rad(theta)
|
||||||
x = np.cos(theta)
|
x = np.cos(theta)
|
||||||
y = np.sin(theta)
|
y = np.sin(theta)
|
||||||
return np.rad2deg(np.arctan2(scale * y, x))
|
stheta = np.rad2deg(np.arctan2(scale * y, x))
|
||||||
theta1 = theta_stretch(self.theta1, width / height)
|
# arctan2 has the range [-pi, pi], we expect [0, 2*pi]
|
||||||
theta2 = theta_stretch(self.theta2, width / height)
|
return (stheta + 360) % 360
|
||||||
|
|
||||||
# Get width and height in pixels
|
theta1 = self.theta1
|
||||||
width, height = self.get_transform().transform((width, height))
|
theta2 = self.theta2
|
||||||
|
|
||||||
|
if (
|
||||||
|
# if we need to stretch the angles because we are distorted
|
||||||
|
width != height
|
||||||
|
# and we are not doing a full circle.
|
||||||
|
#
|
||||||
|
# 0 and 360 do not exactly round-trip through the angle
|
||||||
|
# stretching (due to both float precision limitations and
|
||||||
|
# the difference between the range of arctan2 [-pi, pi] and
|
||||||
|
# this method [0, 360]) so avoid doing it if we don't have to.
|
||||||
|
and not (theta1 != theta2 and theta1 % 360 == theta2 % 360)
|
||||||
|
):
|
||||||
|
theta1 = theta_stretch(self.theta1, width / height)
|
||||||
|
theta2 = theta_stretch(self.theta2, width / height)
|
||||||
|
|
||||||
|
# Get width and height in pixels we need to use
|
||||||
|
# `self.get_data_transform` rather than `self.get_transform`
|
||||||
|
# because we want the transform from dataspace to the
|
||||||
|
# screen space to estimate how big the arc will be in physical
|
||||||
|
# units when rendered (the transform that we get via
|
||||||
|
# `self.get_transform()` goes from an idealized unit-radius
|
||||||
|
# space to screen space).
|
||||||
|
data_to_screen_trans = self.get_data_transform()
|
||||||
|
pwidth, pheight = (data_to_screen_trans.transform((width, height)) -
|
||||||
|
data_to_screen_trans.transform((0, 0)))
|
||||||
inv_error = (1.0 / 1.89818e-6) * 0.5
|
inv_error = (1.0 / 1.89818e-6) * 0.5
|
||||||
if width < inv_error and height < inv_error:
|
|
||||||
|
if pwidth < inv_error and pheight < inv_error:
|
||||||
self._path = Path.arc(theta1, theta2)
|
self._path = Path.arc(theta1, theta2)
|
||||||
return Patch.draw(self, renderer)
|
return Patch.draw(self, renderer)
|
||||||
|
|
||||||
def iter_circle_intersect_on_line(x0, y0, x1, y1):
|
def line_circle_intersect(x0, y0, x1, y1):
|
||||||
dx = x1 - x0
|
dx = x1 - x0
|
||||||
dy = y1 - y0
|
dy = y1 - y0
|
||||||
dr2 = dx * dx + dy * dy
|
dr2 = dx * dx + dy * dy
|
||||||
D = x0 * y1 - x1 * y0
|
D = x0 * y1 - x1 * y0
|
||||||
D2 = D * D
|
D2 = D * D
|
||||||
discrim = dr2 - D2
|
discrim = dr2 - D2
|
||||||
|
if discrim >= 0.0:
|
||||||
# Single (tangential) intersection
|
sign_dy = np.copysign(1, dy) # +/-1, never 0.
|
||||||
if discrim == 0.0:
|
|
||||||
x = (D * dy) / dr2
|
|
||||||
y = (-D * dx) / dr2
|
|
||||||
yield x, y
|
|
||||||
elif discrim > 0.0:
|
|
||||||
# The definition of "sign" here is different from
|
|
||||||
# np.sign: we never want to get 0.0
|
|
||||||
if dy < 0.0:
|
|
||||||
sign_dy = -1.0
|
|
||||||
else:
|
|
||||||
sign_dy = 1.0
|
|
||||||
sqrt_discrim = np.sqrt(discrim)
|
sqrt_discrim = np.sqrt(discrim)
|
||||||
for sign in (1., -1.):
|
return np.array(
|
||||||
x = (D * dy + sign * sign_dy * dx * sqrt_discrim) / dr2
|
[[(D * dy + sign_dy * dx * sqrt_discrim) / dr2,
|
||||||
y = (-D * dx + sign * np.abs(dy) * sqrt_discrim) / dr2
|
(-D * dx + abs(dy) * sqrt_discrim) / dr2],
|
||||||
yield x, y
|
[(D * dy - sign_dy * dx * sqrt_discrim) / dr2,
|
||||||
|
(-D * dx - abs(dy) * sqrt_discrim) / dr2]])
|
||||||
|
else:
|
||||||
|
return np.empty((0, 2))
|
||||||
|
|
||||||
def iter_circle_intersect_on_line_seg(x0, y0, x1, y1):
|
def segment_circle_intersect(x0, y0, x1, y1):
|
||||||
epsilon = 1e-9
|
epsilon = 1e-9
|
||||||
if x1 < x0:
|
if x1 < x0:
|
||||||
x0e, x1e = x1, x0
|
x0e, x1e = x1, x0
|
||||||
|
@ -1668,40 +1686,34 @@ class Arc(Ellipse):
|
||||||
y0e, y1e = y1, y0
|
y0e, y1e = y1, y0
|
||||||
else:
|
else:
|
||||||
y0e, y1e = y0, y1
|
y0e, y1e = y0, y1
|
||||||
x0e -= epsilon
|
xys = line_circle_intersect(x0, y0, x1, y1)
|
||||||
y0e -= epsilon
|
xs, ys = xys.T
|
||||||
x1e += epsilon
|
return xys[
|
||||||
y1e += epsilon
|
(x0e - epsilon < xs) & (xs < x1e + epsilon)
|
||||||
for x, y in iter_circle_intersect_on_line(x0, y0, x1, y1):
|
& (y0e - epsilon < ys) & (ys < y1e + epsilon)
|
||||||
if x0e <= x <= x1e and y0e <= y <= y1e:
|
]
|
||||||
yield x, y
|
|
||||||
|
|
||||||
# Transforms the axes box_path so that it is relative to the unit
|
# Transforms the axes box_path so that it is relative to the unit
|
||||||
# circle in the same way that it is relative to the desired ellipse.
|
# circle in the same way that it is relative to the desired ellipse.
|
||||||
box_path = Path.unit_rectangle()
|
|
||||||
box_path_transform = (transforms.BboxTransformTo(self.axes.bbox)
|
box_path_transform = (transforms.BboxTransformTo(self.axes.bbox)
|
||||||
- self.get_transform())
|
+ self.get_transform().inverted())
|
||||||
box_path = box_path.transformed(box_path_transform)
|
box_path = Path.unit_rectangle().transformed(box_path_transform)
|
||||||
|
|
||||||
thetas = set()
|
thetas = set()
|
||||||
# For each of the point pairs, there is a line segment
|
# For each of the point pairs, there is a line segment
|
||||||
for p0, p1 in zip(box_path.vertices[:-1], box_path.vertices[1:]):
|
for p0, p1 in zip(box_path.vertices[:-1], box_path.vertices[1:]):
|
||||||
x0, y0 = p0
|
xy = segment_circle_intersect(*p0, *p1)
|
||||||
x1, y1 = p1
|
x, y = xy.T
|
||||||
for x, y in iter_circle_intersect_on_line_seg(x0, y0, x1, y1):
|
# arctan2 return [-pi, pi), the rest of our angles are in
|
||||||
theta = np.arccos(x)
|
# [0, 360], adjust as needed.
|
||||||
if y < 0:
|
theta = (np.rad2deg(np.arctan2(y, x)) + 360) % 360
|
||||||
theta = 2 * np.pi - theta
|
thetas.update(theta[(theta1 < theta) & (theta < theta2)])
|
||||||
# Convert radians to angles
|
|
||||||
theta = np.rad2deg(theta)
|
|
||||||
if theta1 < theta < theta2:
|
|
||||||
thetas.add(theta)
|
|
||||||
thetas = sorted(thetas) + [theta2]
|
thetas = sorted(thetas) + [theta2]
|
||||||
|
|
||||||
last_theta = theta1
|
last_theta = theta1
|
||||||
theta1_rad = np.deg2rad(theta1)
|
theta1_rad = np.deg2rad(theta1)
|
||||||
inside = box_path.contains_point((np.cos(theta1_rad),
|
inside = box_path.contains_point(
|
||||||
np.sin(theta1_rad)))
|
(np.cos(theta1_rad), np.sin(theta1_rad))
|
||||||
|
)
|
||||||
|
|
||||||
# save original path
|
# save original path
|
||||||
path_original = self._path
|
path_original = self._path
|
||||||
|
|
|
@ -953,6 +953,7 @@ class PolarAxes(Axes):
|
||||||
return self._yaxis_text_transform + pad_shift, 'center', halign
|
return self._yaxis_text_transform + pad_shift, 'center', halign
|
||||||
|
|
||||||
def draw(self, *args, **kwargs):
|
def draw(self, *args, **kwargs):
|
||||||
|
self._unstale_viewLim()
|
||||||
thetamin, thetamax = np.rad2deg(self._realViewLim.intervalx)
|
thetamin, thetamax = np.rad2deg(self._realViewLim.intervalx)
|
||||||
if thetamin > thetamax:
|
if thetamin > thetamax:
|
||||||
thetamin, thetamax = thetamax, thetamin
|
thetamin, thetamax = thetamax, thetamin
|
||||||
|
|
|
@ -1500,7 +1500,7 @@ def yticks(ticks=None, labels=None, **kwargs):
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
ticks : array-like, optional
|
ticks : array-like, optional
|
||||||
The list of xtick locations. Passing an empty list removes all xticks.
|
The list of ytick locations. Passing an empty list removes all yticks.
|
||||||
labels : array-like, optional
|
labels : array-like, optional
|
||||||
The labels to place at the given *ticks* locations. This argument can
|
The labels to place at the given *ticks* locations. This argument can
|
||||||
only be passed if *ticks* is passed as well.
|
only be passed if *ticks* is passed as well.
|
||||||
|
|
|
@ -43,14 +43,14 @@ STYLE_BLACKLIST = {
|
||||||
|
|
||||||
def _remove_blacklisted_style_params(d, warn=True):
|
def _remove_blacklisted_style_params(d, warn=True):
|
||||||
o = {}
|
o = {}
|
||||||
for key, val in d.items():
|
for key in d: # prevent triggering RcParams.__getitem__('backend')
|
||||||
if key in STYLE_BLACKLIST:
|
if key in STYLE_BLACKLIST:
|
||||||
if warn:
|
if warn:
|
||||||
cbook._warn_external(
|
cbook._warn_external(
|
||||||
"Style includes a parameter, '{0}', that is not related "
|
"Style includes a parameter, '{0}', that is not related "
|
||||||
"to style. Ignoring".format(key))
|
"to style. Ignoring".format(key))
|
||||||
else:
|
else:
|
||||||
o[key] = val
|
o[key] = d[key]
|
||||||
return o
|
return o
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -211,9 +211,9 @@ class _SVGConverter(_Converter):
|
||||||
# Inkscape's output is not localized but gtk's is, so the output
|
# Inkscape's output is not localized but gtk's is, so the output
|
||||||
# stream probably has a mixed encoding. Using the filesystem
|
# stream probably has a mixed encoding. Using the filesystem
|
||||||
# encoding should at least get the filenames right...
|
# encoding should at least get the filenames right...
|
||||||
self._stderr.seek(0)
|
self._proc.stderr.seek(0)
|
||||||
raise ImageComparisonFailure(
|
raise ImageComparisonFailure(
|
||||||
self._stderr.read().decode(
|
self._proc.stderr.read().decode(
|
||||||
sys.getfilesystemencoding(), "replace"))
|
sys.getfilesystemencoding(), "replace"))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -358,9 +358,9 @@ def check_figures_equal(*, extensions=("png", "pdf", "svg"), tol=0):
|
||||||
"""
|
"""
|
||||||
Decorator for test cases that generate and compare two figures.
|
Decorator for test cases that generate and compare two figures.
|
||||||
|
|
||||||
The decorated function must take two arguments, *fig_test* and *fig_ref*,
|
The decorated function must take two keyword arguments, *fig_test*
|
||||||
and draw the test and reference images on them. After the function
|
and *fig_ref*, and draw the test and reference images on them.
|
||||||
returns, the figures are saved and compared.
|
After the function returns, the figures are saved and compared.
|
||||||
|
|
||||||
This decorator should be preferred over `image_comparison` when possible in
|
This decorator should be preferred over `image_comparison` when possible in
|
||||||
order to keep the size of the test suite from ballooning.
|
order to keep the size of the test suite from ballooning.
|
||||||
|
@ -381,6 +381,7 @@ def check_figures_equal(*, extensions=("png", "pdf", "svg"), tol=0):
|
||||||
def test_plot(fig_test, fig_ref):
|
def test_plot(fig_test, fig_ref):
|
||||||
fig_test.subplots().plot([1, 3, 5])
|
fig_test.subplots().plot([1, 3, 5])
|
||||||
fig_ref.subplots().plot([0, 1, 2], [1, 3, 5])
|
fig_ref.subplots().plot([0, 1, 2], [1, 3, 5])
|
||||||
|
|
||||||
"""
|
"""
|
||||||
ALLOWED_CHARS = set(string.digits + string.ascii_letters + '_-[]()')
|
ALLOWED_CHARS = set(string.digits + string.ascii_letters + '_-[]()')
|
||||||
KEYWORD_ONLY = inspect.Parameter.KEYWORD_ONLY
|
KEYWORD_ONLY = inspect.Parameter.KEYWORD_ONLY
|
||||||
|
@ -390,6 +391,11 @@ def check_figures_equal(*, extensions=("png", "pdf", "svg"), tol=0):
|
||||||
_, result_dir = _image_directories(func)
|
_, result_dir = _image_directories(func)
|
||||||
old_sig = inspect.signature(func)
|
old_sig = inspect.signature(func)
|
||||||
|
|
||||||
|
if not {"fig_test", "fig_ref"}.issubset(old_sig.parameters):
|
||||||
|
raise ValueError("The decorated function must have at least the "
|
||||||
|
"parameters 'fig_ref' and 'fig_test', but your "
|
||||||
|
f"function has the signature {old_sig}")
|
||||||
|
|
||||||
@pytest.mark.parametrize("ext", extensions)
|
@pytest.mark.parametrize("ext", extensions)
|
||||||
def wrapper(*args, **kwargs):
|
def wrapper(*args, **kwargs):
|
||||||
ext = kwargs['ext']
|
ext = kwargs['ext']
|
||||||
|
|
|
@ -750,7 +750,11 @@ def test_polar_invertedylim():
|
||||||
def test_polar_invertedylim_rorigin():
|
def test_polar_invertedylim_rorigin():
|
||||||
fig = plt.figure()
|
fig = plt.figure()
|
||||||
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8], polar=True)
|
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8], polar=True)
|
||||||
ax.set_ylim(2, 0)
|
ax.yaxis.set_inverted(True)
|
||||||
|
# Set the rlims to inverted (2, 0) without calling set_rlim, to check that
|
||||||
|
# viewlims are correctly unstaled before draw()ing.
|
||||||
|
ax.plot([0, 0], [0, 2], c="none")
|
||||||
|
ax.margins(0)
|
||||||
ax.set_rorigin(3)
|
ax.set_rorigin(3)
|
||||||
|
|
||||||
|
|
||||||
|
@ -2084,6 +2088,22 @@ class TestScatter:
|
||||||
c=c_case, edgecolors="black", kwargs={}, xsize=xsize,
|
c=c_case, edgecolors="black", kwargs={}, xsize=xsize,
|
||||||
get_next_color_func=get_next_color)
|
get_next_color_func=get_next_color)
|
||||||
|
|
||||||
|
@pytest.mark.style('default')
|
||||||
|
@check_figures_equal(extensions=["png"])
|
||||||
|
def test_scatter_single_color_c(self, fig_test, fig_ref):
|
||||||
|
rgb = [[1, 0.5, 0.05]]
|
||||||
|
rgba = [[1, 0.5, 0.05, .5]]
|
||||||
|
|
||||||
|
# set via color kwarg
|
||||||
|
ax_ref = fig_ref.subplots()
|
||||||
|
ax_ref.scatter(np.ones(3), range(3), color=rgb)
|
||||||
|
ax_ref.scatter(np.ones(4)*2, range(4), color=rgba)
|
||||||
|
|
||||||
|
# set via broadcasting via c
|
||||||
|
ax_test = fig_test.subplots()
|
||||||
|
ax_test.scatter(np.ones(3), range(3), c=rgb)
|
||||||
|
ax_test.scatter(np.ones(4)*2, range(4), c=rgba)
|
||||||
|
|
||||||
|
|
||||||
def _params(c=None, xsize=2, **kwargs):
|
def _params(c=None, xsize=2, **kwargs):
|
||||||
edgecolors = kwargs.pop('edgecolors', None)
|
edgecolors = kwargs.pop('edgecolors', None)
|
||||||
|
@ -6674,3 +6694,33 @@ def test_invisible_axes():
|
||||||
assert fig.canvas.inaxes((200, 200)) is not None
|
assert fig.canvas.inaxes((200, 200)) is not None
|
||||||
ax.set_visible(False)
|
ax.set_visible(False)
|
||||||
assert fig.canvas.inaxes((200, 200)) is None
|
assert fig.canvas.inaxes((200, 200)) is None
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('auto', (True, False, None))
|
||||||
|
def test_unautoscaley(auto):
|
||||||
|
fig, ax = plt.subplots()
|
||||||
|
x = np.arange(100)
|
||||||
|
y = np.linspace(-.1, .1, 100)
|
||||||
|
ax.scatter(x, y)
|
||||||
|
|
||||||
|
post_auto = ax.get_autoscaley_on() if auto is None else auto
|
||||||
|
|
||||||
|
ax.set_ylim((-.5, .5), auto=auto)
|
||||||
|
assert post_auto == ax.get_autoscaley_on()
|
||||||
|
fig.canvas.draw()
|
||||||
|
assert_array_equal(ax.get_ylim(), (-.5, .5))
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('auto', (True, False, None))
|
||||||
|
def test_unautoscalex(auto):
|
||||||
|
fig, ax = plt.subplots()
|
||||||
|
x = np.arange(100)
|
||||||
|
y = np.linspace(-.1, .1, 100)
|
||||||
|
ax.scatter(y, x)
|
||||||
|
|
||||||
|
post_auto = ax.get_autoscalex_on() if auto is None else auto
|
||||||
|
|
||||||
|
ax.set_xlim((-.5, .5), auto=auto)
|
||||||
|
assert post_auto == ax.get_autoscalex_on()
|
||||||
|
fig.canvas.draw()
|
||||||
|
assert_array_equal(ax.get_xlim(), (-.5, .5))
|
||||||
|
|
|
@ -253,6 +253,29 @@ def test_dpi_ratio_change():
|
||||||
assert qt_canvas.get_width_height() == (600, 240)
|
assert qt_canvas.get_width_height() == (600, 240)
|
||||||
assert (fig.get_size_inches() == (5, 2)).all()
|
assert (fig.get_size_inches() == (5, 2)).all()
|
||||||
|
|
||||||
|
p.return_value = 1.5
|
||||||
|
|
||||||
|
assert qt_canvas._dpi_ratio == 1.5
|
||||||
|
|
||||||
|
qt_canvas.draw()
|
||||||
|
qApp.processEvents()
|
||||||
|
# this second processEvents is required to fully run the draw.
|
||||||
|
# On `update` we notice the DPI has changed and trigger a
|
||||||
|
# resize event to refresh, the second processEvents is
|
||||||
|
# required to process that and fully update the window sizes.
|
||||||
|
qApp.processEvents()
|
||||||
|
|
||||||
|
# The DPI and the renderer width/height change
|
||||||
|
assert fig.dpi == 180
|
||||||
|
assert qt_canvas.renderer.width == 900
|
||||||
|
assert qt_canvas.renderer.height == 360
|
||||||
|
|
||||||
|
# The actual widget size and figure physical size don't change
|
||||||
|
assert size.width() == 600
|
||||||
|
assert size.height() == 240
|
||||||
|
assert qt_canvas.get_width_height() == (600, 240)
|
||||||
|
assert (fig.get_size_inches() == (5, 2)).all()
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.backend('Qt5Agg')
|
@pytest.mark.backend('Qt5Agg')
|
||||||
def test_subplottool():
|
def test_subplottool():
|
||||||
|
|
|
@ -205,3 +205,9 @@ def test_gid():
|
||||||
for gid, obj in gdic.items():
|
for gid, obj in gdic.items():
|
||||||
if include(gid, obj):
|
if include(gid, obj):
|
||||||
assert gid in buf
|
assert gid in buf
|
||||||
|
|
||||||
|
|
||||||
|
def test_savefig_tight():
|
||||||
|
# Check that the draw-disabled renderer correctly disables open/close_group
|
||||||
|
# as well.
|
||||||
|
plt.savefig(BytesIO(), format="svgz", bbox_inches="tight")
|
||||||
|
|
|
@ -35,6 +35,11 @@ def _get_testable_interactive_backends():
|
||||||
if reason:
|
if reason:
|
||||||
backend = pytest.param(
|
backend = pytest.param(
|
||||||
backend, marks=pytest.mark.skip(reason=reason))
|
backend, marks=pytest.mark.skip(reason=reason))
|
||||||
|
elif backend == 'wxagg' and sys.platform == 'darwin':
|
||||||
|
# ignore on OSX because that's currently broken (github #16849)
|
||||||
|
backend = pytest.param(
|
||||||
|
backend,
|
||||||
|
marks=pytest.mark.xfail(reason='github #16849'))
|
||||||
backends.append(backend)
|
backends.append(backend)
|
||||||
return backends
|
return backends
|
||||||
|
|
||||||
|
@ -47,6 +52,7 @@ def _get_testable_interactive_backends():
|
||||||
_test_script = """\
|
_test_script = """\
|
||||||
import importlib
|
import importlib
|
||||||
import importlib.util
|
import importlib.util
|
||||||
|
import io
|
||||||
import sys
|
import sys
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
|
|
||||||
|
@ -102,7 +108,23 @@ timer.add_callback(FigureCanvasBase.key_press_event, fig.canvas, "q")
|
||||||
# Trigger quitting upon draw.
|
# Trigger quitting upon draw.
|
||||||
fig.canvas.mpl_connect("draw_event", lambda event: timer.start())
|
fig.canvas.mpl_connect("draw_event", lambda event: timer.start())
|
||||||
|
|
||||||
|
result = io.BytesIO()
|
||||||
|
fig.savefig(result, format='png')
|
||||||
|
|
||||||
plt.show()
|
plt.show()
|
||||||
|
|
||||||
|
# Ensure that the window is really closed.
|
||||||
|
plt.pause(0.5)
|
||||||
|
|
||||||
|
# Test that saving works after interactive window is closed, but the figure is
|
||||||
|
# not deleted.
|
||||||
|
result_after = io.BytesIO()
|
||||||
|
fig.savefig(result_after, format='png')
|
||||||
|
|
||||||
|
if not backend.startswith('qt5') and sys.platform == 'darwin':
|
||||||
|
# FIXME: This should be enabled everywhere once Qt5 is fixed on macOS to
|
||||||
|
# not resize incorrectly.
|
||||||
|
assert_equal(result.getvalue(), result_after.getvalue())
|
||||||
"""
|
"""
|
||||||
_test_timeout = 10 # Empirically, 1s is not enough on Travis.
|
_test_timeout = 10 # Empirically, 1s is not enough on Travis.
|
||||||
|
|
||||||
|
@ -110,9 +132,10 @@ _test_timeout = 10 # Empirically, 1s is not enough on Travis.
|
||||||
@pytest.mark.parametrize("backend", _get_testable_interactive_backends())
|
@pytest.mark.parametrize("backend", _get_testable_interactive_backends())
|
||||||
@pytest.mark.flaky(reruns=3)
|
@pytest.mark.flaky(reruns=3)
|
||||||
def test_interactive_backend(backend):
|
def test_interactive_backend(backend):
|
||||||
proc = subprocess.run([sys.executable, "-c", _test_script],
|
proc = subprocess.run(
|
||||||
env={**os.environ, "MPLBACKEND": backend},
|
[sys.executable, "-c", _test_script],
|
||||||
timeout=_test_timeout)
|
env={**os.environ, "MPLBACKEND": backend, "SOURCE_DATE_EPOCH": "0"},
|
||||||
|
timeout=_test_timeout)
|
||||||
if proc.returncode:
|
if proc.returncode:
|
||||||
pytest.fail("The subprocess returned with non-zero exit status "
|
pytest.fail("The subprocess returned with non-zero exit status "
|
||||||
f"{proc.returncode}.")
|
f"{proc.returncode}.")
|
||||||
|
@ -124,7 +147,8 @@ def test_interactive_backend(backend):
|
||||||
def test_webagg():
|
def test_webagg():
|
||||||
pytest.importorskip("tornado")
|
pytest.importorskip("tornado")
|
||||||
proc = subprocess.Popen([sys.executable, "-c", _test_script],
|
proc = subprocess.Popen([sys.executable, "-c", _test_script],
|
||||||
env={**os.environ, "MPLBACKEND": "webagg"})
|
env={**os.environ, "MPLBACKEND": "webagg",
|
||||||
|
"SOURCE_DATE_EPOCH": "0"})
|
||||||
url = "http://{}:{}".format(
|
url = "http://{}:{}".format(
|
||||||
mpl.rcParams["webagg.address"], mpl.rcParams["webagg.port"])
|
mpl.rcParams["webagg.address"], mpl.rcParams["webagg.port"])
|
||||||
timeout = time.perf_counter() + _test_timeout
|
timeout = time.perf_counter() + _test_timeout
|
||||||
|
|
|
@ -108,3 +108,26 @@ def test_tight_pcolorfast():
|
||||||
# Previously, the bbox would include the area of the image clipped out by
|
# Previously, the bbox would include the area of the image clipped out by
|
||||||
# the axes, resulting in a very tall image given the y limits of (0, 0.1).
|
# the axes, resulting in a very tall image given the y limits of (0, 0.1).
|
||||||
assert width > height
|
assert width > height
|
||||||
|
|
||||||
|
|
||||||
|
def test_noop_tight_bbox():
|
||||||
|
from PIL import Image
|
||||||
|
x_size, y_size = (10, 7)
|
||||||
|
dpi = 100
|
||||||
|
# make the figure just the right size up front
|
||||||
|
fig = plt.figure(frameon=False, dpi=dpi, figsize=(x_size/dpi, y_size/dpi))
|
||||||
|
ax = plt.Axes(fig, [0., 0., 1., 1.])
|
||||||
|
fig.add_axes(ax)
|
||||||
|
ax.set_axis_off()
|
||||||
|
ax.get_xaxis().set_visible(False)
|
||||||
|
ax.get_yaxis().set_visible(False)
|
||||||
|
|
||||||
|
data = np.arange(x_size * y_size).reshape(y_size, x_size)
|
||||||
|
ax.imshow(data)
|
||||||
|
out = BytesIO()
|
||||||
|
fig.savefig(out, bbox_inches='tight', pad_inches=0)
|
||||||
|
out.seek(0)
|
||||||
|
im = np.asarray(Image.open(out))
|
||||||
|
assert (im[:, :, 3] == 255).all()
|
||||||
|
assert not (im[:, :, :3] == 255).all()
|
||||||
|
assert im.shape == (7, 10, 4)
|
||||||
|
|
|
@ -718,3 +718,24 @@ def test_EventCollection_nosort():
|
||||||
arr = np.array([3, 2, 1, 10])
|
arr = np.array([3, 2, 1, 10])
|
||||||
coll = EventCollection(arr)
|
coll = EventCollection(arr)
|
||||||
np.testing.assert_array_equal(arr, np.array([3, 2, 1, 10]))
|
np.testing.assert_array_equal(arr, np.array([3, 2, 1, 10]))
|
||||||
|
|
||||||
|
|
||||||
|
def test_blended_collection_autolim():
|
||||||
|
a = [1, 2, 4]
|
||||||
|
height = .2
|
||||||
|
|
||||||
|
xy_pairs = np.column_stack([np.repeat(a, 2), np.tile([0, height], len(a))])
|
||||||
|
line_segs = xy_pairs.reshape([len(a), 2, 2])
|
||||||
|
|
||||||
|
f, ax = plt.subplots()
|
||||||
|
trans = mtransforms.blended_transform_factory(ax.transData, ax.transAxes)
|
||||||
|
ax.add_collection(LineCollection(line_segs, transform=trans))
|
||||||
|
ax.autoscale_view(scalex=True, scaley=False)
|
||||||
|
np.testing.assert_allclose(ax.get_xlim(), [1., 4.])
|
||||||
|
|
||||||
|
|
||||||
|
def test_singleton_autolim():
|
||||||
|
fig, ax = plt.subplots()
|
||||||
|
ax.scatter(0, 0)
|
||||||
|
np.testing.assert_allclose(ax.get_ylim(), [-0.06, 0.06])
|
||||||
|
np.testing.assert_allclose(ax.get_xlim(), [-0.06, 0.06])
|
||||||
|
|
|
@ -487,3 +487,12 @@ def test_removed_axis():
|
||||||
fig, axs = plt.subplots(2, sharex=True)
|
fig, axs = plt.subplots(2, sharex=True)
|
||||||
axs[0].remove()
|
axs[0].remove()
|
||||||
fig.canvas.draw()
|
fig.canvas.draw()
|
||||||
|
|
||||||
|
|
||||||
|
@check_figures_equal(extensions=["svg", "pdf", "eps", "png"])
|
||||||
|
def test_animated_with_canvas_change(fig_test, fig_ref):
|
||||||
|
ax_ref = fig_ref.subplots()
|
||||||
|
ax_ref.plot(range(5))
|
||||||
|
|
||||||
|
ax_test = fig_test.subplots()
|
||||||
|
ax_test.plot(range(5), animated=True)
|
||||||
|
|
|
@ -24,3 +24,11 @@ def test_height_ratios():
|
||||||
"""
|
"""
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
gridspec.GridSpec(1, 1, height_ratios=[2, 1, 3])
|
gridspec.GridSpec(1, 1, height_ratios=[2, 1, 3])
|
||||||
|
|
||||||
|
|
||||||
|
def test_repr():
|
||||||
|
ss = gridspec.GridSpec(2, 2,
|
||||||
|
height_ratios=(3, 1),
|
||||||
|
width_ratios=(1, 3))
|
||||||
|
assert repr(ss) == \
|
||||||
|
"GridSpec(2, 2, height_ratios=(3, 1), width_ratios=(1, 3))"
|
||||||
|
|
|
@ -490,3 +490,60 @@ def test_fancyarrow_units():
|
||||||
fig, ax = plt.subplots()
|
fig, ax = plt.subplots()
|
||||||
arrow = FancyArrowPatch((0, dtime), (0.01, dtime))
|
arrow = FancyArrowPatch((0, dtime), (0.01, dtime))
|
||||||
ax.add_patch(arrow)
|
ax.add_patch(arrow)
|
||||||
|
|
||||||
|
|
||||||
|
@image_comparison(["large_arc.svg"], style="mpl20")
|
||||||
|
def test_large_arc():
|
||||||
|
fig, (ax1, ax2) = plt.subplots(1, 2)
|
||||||
|
x = 210
|
||||||
|
y = -2115
|
||||||
|
diameter = 4261
|
||||||
|
for ax in [ax1, ax2]:
|
||||||
|
a = mpatches.Arc((x, y), diameter, diameter, lw=2, color='k')
|
||||||
|
ax.add_patch(a)
|
||||||
|
ax.set_axis_off()
|
||||||
|
ax.set_aspect('equal')
|
||||||
|
# force the high accuracy case
|
||||||
|
ax1.set_xlim(7, 8)
|
||||||
|
ax1.set_ylim(5, 6)
|
||||||
|
|
||||||
|
# force the low accuracy case
|
||||||
|
ax2.set_xlim(-25000, 18000)
|
||||||
|
ax2.set_ylim(-20000, 6600)
|
||||||
|
|
||||||
|
|
||||||
|
@image_comparison(["all_quadrants_arcs.svg"], style="mpl20")
|
||||||
|
def test_rotated_arcs():
|
||||||
|
fig, ax_arr = plt.subplots(2, 2, squeeze=False, figsize=(10, 10))
|
||||||
|
|
||||||
|
scale = 10_000_000
|
||||||
|
diag_centers = ((-1, -1), (-1, 1), (1, 1), (1, -1))
|
||||||
|
on_axis_centers = ((0, 1), (1, 0), (0, -1), (-1, 0))
|
||||||
|
skews = ((2, 2), (2, 1/10), (2, 1/100), (2, 1/1000))
|
||||||
|
|
||||||
|
for ax, (sx, sy) in zip(ax_arr.ravel(), skews):
|
||||||
|
k = 0
|
||||||
|
for prescale, centers in zip((1 - .0001, (1 - .0001) / np.sqrt(2)),
|
||||||
|
(on_axis_centers, diag_centers)):
|
||||||
|
for j, (x_sign, y_sign) in enumerate(centers, start=k):
|
||||||
|
a = mpatches.Arc(
|
||||||
|
(x_sign * scale * prescale,
|
||||||
|
y_sign * scale * prescale),
|
||||||
|
scale * sx,
|
||||||
|
scale * sy,
|
||||||
|
lw=4,
|
||||||
|
color=f"C{j}",
|
||||||
|
zorder=1 + j,
|
||||||
|
angle=np.rad2deg(np.arctan2(y_sign, x_sign)) % 360,
|
||||||
|
label=f'big {j}',
|
||||||
|
gid=f'big {j}'
|
||||||
|
)
|
||||||
|
ax.add_patch(a)
|
||||||
|
|
||||||
|
k = j+1
|
||||||
|
ax.set_xlim(-scale / 4000, scale / 4000)
|
||||||
|
ax.set_ylim(-scale / 4000, scale / 4000)
|
||||||
|
ax.axhline(0, color="k")
|
||||||
|
ax.axvline(0, color="k")
|
||||||
|
ax.set_axis_off()
|
||||||
|
ax.set_aspect("equal")
|
||||||
|
|
|
@ -9,31 +9,32 @@ import matplotlib as mpl
|
||||||
from matplotlib import pyplot as plt
|
from matplotlib import pyplot as plt
|
||||||
|
|
||||||
|
|
||||||
def test_pyplot_up_to_date():
|
def test_pyplot_up_to_date(tmpdir):
|
||||||
gen_script = Path(mpl.__file__).parents[2] / "tools/boilerplate.py"
|
gen_script = Path(mpl.__file__).parents[2] / "tools/boilerplate.py"
|
||||||
if not gen_script.exists():
|
if not gen_script.exists():
|
||||||
pytest.skip("boilerplate.py not found")
|
pytest.skip("boilerplate.py not found")
|
||||||
orig_contents = Path(plt.__file__).read_text()
|
orig_contents = Path(plt.__file__).read_text()
|
||||||
try:
|
plt_file = tmpdir.join('pyplot.py')
|
||||||
subprocess.run([sys.executable, str(gen_script)], check=True)
|
plt_file.write_text(orig_contents, 'utf-8')
|
||||||
new_contents = Path(plt.__file__).read_text()
|
|
||||||
|
|
||||||
if orig_contents != new_contents:
|
subprocess.run([sys.executable, str(gen_script), str(plt_file)],
|
||||||
diff_msg = '\n'.join(
|
check=True)
|
||||||
difflib.unified_diff(
|
new_contents = plt_file.read_text('utf-8')
|
||||||
orig_contents.split('\n'), new_contents.split('\n'),
|
|
||||||
fromfile='found pyplot.py',
|
if orig_contents != new_contents:
|
||||||
tofile='expected pyplot.py',
|
diff_msg = '\n'.join(
|
||||||
n=0, lineterm=''))
|
difflib.unified_diff(
|
||||||
pytest.fail(
|
orig_contents.split('\n'), new_contents.split('\n'),
|
||||||
"pyplot.py is not up-to-date. Please run "
|
fromfile='found pyplot.py',
|
||||||
"'python tools/boilerplate.py' to update pyplot.py. "
|
tofile='expected pyplot.py',
|
||||||
"This needs to be done from an environment where your "
|
n=0, lineterm=''))
|
||||||
"current working copy is installed (e.g. 'pip install -e'd). "
|
pytest.fail(
|
||||||
"Here is a diff of unexpected differences:\n%s" % diff_msg
|
"pyplot.py is not up-to-date. Please run "
|
||||||
)
|
"'python tools/boilerplate.py' to update pyplot.py. "
|
||||||
finally:
|
"This needs to be done from an environment where your "
|
||||||
Path(plt.__file__).write_text(orig_contents)
|
"current working copy is installed (e.g. 'pip install -e'd). "
|
||||||
|
"Here is a diff of unexpected differences:\n%s" % diff_msg
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_pyplot_box():
|
def test_pyplot_box():
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user