freemt commited on
Commit
dab2de2
1 Parent(s): 07f1d23

Update aligned pairs plot

Browse files
.gitignore CHANGED
@@ -1 +1,6 @@
1
  .venv
 
 
 
 
 
1
  .venv
2
+ radiobee-aligner-pad.txt
3
+ .gitnore
4
+ radiobee\en2zh_tokens.py
5
+ radiobee/en2zh_tokens.py
6
+ **/__pycache__/
README.md CHANGED
@@ -1,5 +1,5 @@
1
  ---
2
- title: Radiobee Aligner
3
  emoji: 🚧
4
  colorFrom: blue
5
  colorTo: red
1
  ---
2
+ title: radiobee aligner
3
  emoji: 🚧
4
  colorFrom: blue
5
  colorTo: red
data/df1.lzma ADDED
Binary file (49.8 kB). View file
data/lst1.lzma ADDED
Binary file (29.7 kB). View file
data/lst2.lzma ADDED
Binary file (17.3 kB). View file
data/pad.py ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import joblib
2
+ from importlib import import_module
3
+ import radiobee
4
+
5
+ import matplotlib.pyplot as plt
6
+ import numpy as np
7
+ import pandas as pd
8
+ import seaborn as sns
9
+ sns.set()
10
+ sns.set_style("darkgrid")
11
+ plt.ion()
12
+
13
+ for mod in ["lists2cmat", ]:
14
+ globals()[mod] = getattr(import_module(f"{radiobee.__name__}.{mod}"), mod)
15
+
16
+ text1 = joblib.load("data/text1.lzma")
17
+ text2 = joblib.load("data/text2.lzma")
18
+ df1 = joblib.load("data/df1.lzma")
19
+ lst1 = joblib.load("data/lst1.lzma")
20
+ lst2 = joblib.load("data/lst2.lzma")
21
+
22
+ cmat = lists2cmat(lst1, lst2)
23
+ sns.heatmap(cmat, cmap="viridis_r").invert_yaxis()
data/shakespeare_en500.txt ADDED
@@ -0,0 +1,500 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright © Foreign Language Teaching and Research Press 2016
2
+ All rights reserved. No part of this publication may be reproduced or distributed by any means, or stored in a database or retrieval system, without the prior written permission of Foreign Language Teaching and Research Press.
3
+ Published by Foreign Language Teaching and Research Press
4
+ No. 19 Xisanhuan Beilu
5
+ http://www.fltrp.com
6
+ The Tempest
7
+ Copyright©The Royal Shakespeare Company, 2007
8
+ All rights reserved
9
+ Published by arrangement with Random House, an imprint of the Random House Publishing Group, a division of Random House, Inc.
10
+ ISBN 978-7-5135-7223-1
11
+ Introduction to The Tempest
12
+ The Tempest
13
+ User's Guide
14
+ 4 In der Beschränkung zeigt sich erst der Meister, / Und das Gesetz nur kann uns Freiheit geben. 参见http://www.business-it.nl/files/7d413a5dca62fc735a072b16fbf050b1-27.php.
15
+ 5 Vergebens werden ungebundene Geister / Nach der Vollendung reiner Höhe streben. 参见http://www.cosmiq.de/qa/show/3454062/Vergebens-werden-ungebundne-Geister-Nach-der-Vollendung-reiner-Hoehe-streben-Was-ist-dieBedeutung-dieser-2-Verse-Ich-komm-nicht-drauf/t.
16
+ Introduction to The Tempest
17
+ The Tempest was almost certainly Shakespeare's last solo-authored play. We do not know whether he anticipated that this would be the case. It was also the first play to be printed in the First Folio. Again, we do not know whether it was given pride of place because the editors of the Folio regarded it as a showpiece – the summation of the master's art – or for the more mundane reason that they had a clean copy in the clear hand of the scribe Ralph Crane, which would have given the compositors a relatively easy start as they set to work on the mammoth task of typesetting nearly a million words of Shakespeare. Whether it found its position by chance or design, The Tempest's place at the end of Shakespeare's career and the beginning of his collected works has profoundly shaped responses to the play ever since the early nineteenth century. It has come to be regarded as the touchstone of Shakespearean interpretation.
18
+ The narrative is concentrated on questions of mastery and rule. During the tempest in the opening scene, the normal social order is out of joint: the boatswain commands the courtiers in the knowledge that the roaring waves care nothing for 'the name of king'. Then the back story, unfolded at length in Act 1 scene 2, tells of conspirators who do not respect the title of duke: we learn of Prospero's loss of power in Milan and the compensatory command he has gained over Ariel and Caliban on the island. The Ferdinand and Miranda love-knot is directed towards the future government of Milan and Naples. There is further politic plotting: Sebastian and Antonio's plan to murder King Alonso and good Gonzalo, the madcap scheme of the base-born characters to overthrow Prospero and make drunken butler Stephano king of the island. The theatrical coups performed by Prospero, assisted by Ariel and the other spirits of the island – the freezing of the conspirators, the harpy and the vanishing banquet, the masque of goddesses and agricultural workers, the revelation of the lovers playing at chess – all serve the purpose of requiting the sins of the past, restoring order in the present and preparing for a harmonious future. Once the work is done, Ariel is released (with a pang) and Prospero is ready to prepare his own spirit for death. Even Caliban will 'seek for grace'.
19
+ But Shakespeare never keeps it simple. Prospero's main aim in conjuring up the storm and bringing the court to the island is to force his usurping brother Antonio into repentance. Yet when the climactic confrontation comes, Antonio does not say a word in reply to Prospero's combination of forgiveness and demand. He wholly fails to follow the good example set by Alonso a few lines before. As for Antonio's sidekick Sebastian, he has the temerity to ascribe Prospero's magical foresight to demonic influence. For all the powers at Prospero's command, there is no way of predicting or controlling human nature. A conscience cannot be created where there is none.
20
+ Samuel Taylor Coleridge described Prospero as 'the very Shakespeare, as it were, of the tempest'. In other words, the leading character's conjuring up of the storm in the opening scene corresponds to the dramatist's conjuring up of the whole world of the play. The art of Prospero harnesses the power of nature in order to bring the other Italian characters to join him in his exile; by the same account, the art of Shakespeare transforms the platform of the stage into a ship at sea and then 'an uninhabited island'. 'Art' is the play's key word. Caliban is Prospero's 'other' because he represents the state of nature. In the Darwinian nineteenth century, he was recast as the 'missing link' between humankind and our animal ancestors.
21
+ Prospero's back story tells of a progression from the 'liberal arts' that offered a training for governors to the more dangerous 'art' of magic. Magical thinking was universal in the age of Shakespeare. Everyone was brought up to believe that there was another realm beyond that of nature, a realm of the spirit and of spirits. 'Natural' and 'demonic' magic were the two branches of the study and manipulation of preternatural phenomena. Magic meant the knowledge of hidden things and the art of working wonders. For some, it was the highest form of natural philosophy: the word came from magia, the ancient Persian term for wisdom. The 'occult philosophy', as it was known, postulated a hierarchy of powers, with influence descending from disembodied ('intellectual') angelic spirits to the stellar and planetary world of the heavens to earthly things and their physical changes. The magician ascends to knowledge of higher powers and draws them down artificially to produce wonderful effects. Cornelius Agrippa, author of the influential De occulta philosophia, argued that 'ceremonial magic' was needed in order to reach the angelic intelligences above the stars. This was the highest and most dangerous level of activity, since it was all too easy – as Christopher Marlowe's Dr. Faustus found – to conjure up a devil instead of an angel. The more common form of 'natural magic' involved 'marrying' heaven to earth, working with the occult correspondences between the stars and the elements of the material world. The enduring conception of astrological influences is a vestige of this mode of thought. For a Renaissance mage such as Girolamo Cardano, who practised in Milan, medicine, natural philosophy, mathematics, astrology and dream interpretation were all intimately connected.
22
+ But natural magic could never escape its demonic shadow. For every learned mage such as Agrippa or Cardano, there were a thousand village 'wise women' practising folk medicine and fortunetelling. All too often, the latter found themselves demonized as witches, blamed for crop failure, livestock disease and the other ills of life in the pre-modern era. Prospero is keen to contrast his own white magic with the black arts of Sycorax, Caliban's mother, but the play establishes strong parallels between them. He was exiled from Milan to the island because his devotion to his secret studies gave Antonio the opportunity to usurp the dukedom, whilst Sycorax was exiled from Algiers to the island because she was accused of witchcraft; he arrived with his young daughter, whilst she arrived pregnant with the child she had supposedly conceived by sleeping with the devil. Each of them can command the tides and manipulate the spirit-world that is embodied by Ariel. When Prospero comes to renounce his magic, he describes his powers in words borrowed from the incantation of another witch, Medea in Ovid's great storehouse of ancient mythological tales, the Metamorphoses. Prospero at some level registers his own kinship with Sycorax when he says of Caliban 'this thing of darkness I / Acknowledge mine'. The splitting of subject and verb across the line ending here, ensuring a moment's hesitation in the acknowledgement, is an extreme instance of the suppleness with which late Shakespeare handles his iambic pentameter verse.
23
+ Shakespeare loved to set up oppositions, then shade his black and white into grey areas of moral complexity. In Milan, Prospero's inward-looking study of the liberal arts had led to the loss of power and the establishment of tyranny. On the island he seeks to make amends by applying what he has learned, by using active magic to bring repentance, restore his dukedom and set up a dynastic marriage. Yet at the beginning of the fifth act he sees that to be truly human is a matter not of exercising wisdom for the purposes of rule, but of practising a more strictly Christian version of virtue. For sixteenth-century humanists, education in princely virtue meant the cultivation for political ends of wisdom, magnanimity, temperance and integrity. For Prospero what finally matters is kindness. And this is something that the master learns from his pupil: it is Ariel who teaches Prospero about 'feeling', not vice versa.
24
+ Ariel represents fire and air, concord and music, loyal service. Caliban is of the earth, associated with discord, drunkenness and rebellion. Ariel's medium of expression is delicate verse, whilst Caliban's is for the most part a robust, often ribald, prose like that of the jester Trinculo and drunken butler Stephano. But, astonishingly, it is Caliban who speaks the play's most beautiful verse when he hears the music of Ariel. Even in prose, Caliban has a wonderful attunement to the natural environment: he knows every corner, every species of the island. Prospero calls him 'A devil, a born devil, on whose nature / Nurture can never stick', yet in the very next speech Caliban enters with the line 'Pray you tread softly, that the blind mole may not hear a footfall', words of such strong imagination that Prospero's claim is instantly belied.
25
+ Caliban's purported sexual assault on Miranda shows that Prospero failed in his attempt to tame the animal instincts of the 'man-monster' and educate him into humanity. But who bears responsibility for the failure? Could it be that the problem arises from what Prospero has imprinted on Caliban's memory, not from the latter's nature? Caliban initially welcomed Prospero to the island and offered to share its fruits, every bit in the manner of the 'noble savages' in Michel de Montaigne's essay 'Of the Cannibals', which was another source from which Shakespeare quoted in the play (Gonzalo's Utopian 'golden age' vision of how he would govern the isle is borrowed from the English translation of Montaigne). Caliban only acts basely after Prospero has printed that baseness on him; what makes Caliban 'filth' may be the lessons in which Prospero has taught him that he is 'filth'.
26
+ Caliban understands the power of the book: as fashioners of modern coups d'état begin by seizing the television station, so he stresses that the rebellion against Prospero must begin by taking possession of his books. But Stephano has another book. 'Here is that which will give language to you', he says to Caliban, replicating Prospero's gaining of control through language – but in a different mode. Textual inculcation is replaced by intoxication: the book that is kissed is the bottle. The dialogic spirit that is fostered by Shakespeare's technique of scenic counterpoint thus calls into question Prospero's use of books. If Stephano and Trinculo achieve through their alcohol what Prospero achieves through his teaching (in each case Caliban is persuaded to serve and to share the fruits of the isle), is not that teaching exposed as potentially nothing more than a means of social control? Prospero often seems more interested in the power-structure that is established by his schoolmastering than in the substance of what he teaches. It is hard to see how making Ferdinand carry logs is intended to inculcate virtue; its purpose is to elicit submission.
27
+ Arrival on an island uninhabited by Europeans, talk of 'plantation', an encounter with a 'savage' in which alcohol is exchanged for survival skills, a process of language learning in which it is made clear who is master and who is slave, fear that the slave will impregnate the master's daughter, the desire to make the savage seek for Christian 'grace' (though also a proposal that he should be shipped to England and exhibited for profit), references to the dangerous weather of the Bermudas and to a 'brave new world': in all these respects, The Tempest conjures up the spirit of European colonialism. Shakespeare had contacts with members of the Virginia Company, which had been established by royal charter in 1606 and was instrumental in the foundation of the Jamestown colony in America the following year. Some time in the autumn of 1610, a letter reached England describing how a fleet sent to reinforce the colony had been broken up by a storm in the Caribbean; the ship carrying the new governor had been driven to Bermuda, where the crew and passengers had wintered. Though the letter was not published at the time, it circulated in manuscript and inspired at least two pamphlets about these events. Scholars debate the extent to which Shakespeare made direct use of these materials, but certain details of the storm and the island seem to be derived from them. There is no doubt that the seemingly miraculous survival of the governor's party and the fertile environment they discovered in the Bahamas were topics of great public interest at the time of the play.
28
+ The British Empire, the slave trade and the riches of the spice routes lay in the future. Shakespeare's play is set in the Mediterranean, not the Caribbean. Caliban cannot strictly be described as a native of the island. And yet the play intuits the dynamic of colonial possession and dispossession with such uncanny power that in 1950 a book by Octave Mannoni called The Psychology of Colonisation could argue that the process functioned by means of a pair of reciprocal neuroses: the 'Prospero complex' on the part of the colonizer and the 'Caliban complex' on that of the colonized. It was in response to Mannoni that Frantz Fanon wrote Black Skin, White Masks, a book that did much to shape the intellectual terrain of the 'post-colonial' era. For many Anglophone Caribbean writers of the late twentieth century, The Tempest, and the figure of Caliban in particular, became a focal point for discovery of their own literary voices. The play is less a reflection of imperial history – after all, Prospero is an exile, not a venturer – than an anticipation of it.
29
+ As regular players at royal command performances in the Whitehall Palace, the King's Men knew that from the end of 1608 onwards, the teenage Princess Elizabeth was resident at court. A cultured young woman who enjoyed music and dancing, she participated in court festivals and in 1610 danced in a masque called Tethys. Masques – performed by a mixed cast of royalty, courtiers and professional actors, staged with spectacular scenery and elaborate music – were the height of fashion at court in these years. Shakespeare's friend and rival Ben Jonson, working in conjunction with the designer Inigo Jones, was carving out a role for himself as the age's leading masque-wright. In 1608 he introduced the 'antimasque' (or 'antemasque'), a convention whereby grotesque figures known as 'antics' danced boisterously prior to the graceful and harmonious masque itself. Shakespeare nods to contemporary fashion by including a betrothal masque within the action of The Tempest, together with the antimasque farce of Caliban, Stephano and Trinculo smelling of horse-piss, stealing clothes from a line and being chased away by dogs. One almost wonders whether the figure of Prospero is a gentle parody of Ben Jonson: his theatrical imagination is bound by the classical unities of time and place (as Jonson's was) and he stages a court masque (as Jonson did). Perhaps this is why a few years later, in his Bartholomew Fair, Jonson parodied The Tempest in return.
30
+ Prospero's Christian language reaches its most sustained pitch in the epilogue, but his final request is for the indulgence not of God but of the audience. At the last moment, humanist learning is replaced not by Christian but by theatrical faith. Because of this it has been possible for the play to be read, as it so often has been since the Romantic period, as Shakespeare's defence of his own dramatic art. Ironically, though, the play itself is profoundly sceptical of the power of the book and even of the theatre. The book of art is drowned, whilst the masque and its players dissolve into vacancy like a 'baseless fabric' or a dream.
31
+ KEY FACTS
32
+ PLOT: Twelve years ago Prospero, the Duke of Milan, was usurped by his brother, Antonio, with the help of Alonso, King of Naples, and the King's brother Sebastian. Prospero and his baby daughter Miranda were put to sea and landed on a distant island where ever since, by the use of his magic art, he has ruled over the spirit Ariel and the savage Caliban. He uses his powers to raise a storm which shipwrecks his enemies on the island. Alonso searches for his son, Ferdinand, although fearing him to be drowned. Sebastian plots to kill Alonso and seize the crown. The drunken butler, Stephano, and the jester, Trinculo, encounter Caliban and are persuaded by him to kill Prospero so that they can rule the island. Ferdinand meets Miranda and they fall instantly in love. Prospero sets heavy tasks to test Ferdinand and, when satisfied, presents the young couple with a betrothal masque. As Prospero's plan draws to its climax, he confronts his enemies and forgives them. Prospero grants Ariel his freedom and prepares to leave the island for Milan.
33
+ MAJOR PARTS: (with percentage of lines/number of speeches/scenes on stage) Prospero (30%/115/5), Ariel (9%/45/6), Caliban (8%/50/5), Stephano (7%/60/4), Gonzalo (7%/52/4), Sebastian (5%/67/4), Antonio (6%/57/4), Miranda (6%/49/4), Ferdinand (6%/31/4), Alonso (5%/40/4), Trinculo (4%/39/4).
34
+ LINGUISTIC MEDIUM: 80% verse, 20% prose.
35
+ DATE: 1611. Performed at court, 1 November 1611; uses source material not available before autumn 1610.
36
+ SOURCES: No known source for main plot, but some details of the tempest and the island seem to derive from William Strachey, A True Reportory of the Wreck and Redemption of Sir Thomas Gates, Knight (written 1610, published in Purchas his Pilgrims, 1625) and perhaps Sylvester Jourdain, A Discovery of the Bermudas (1610) and the Virginia Company's pamphlet A True Declaration of the Estate of the Colony in Virginia (1610); several allusions to Virgil's Aeneid and Ovid's Metamorphoses (most notably the imitation in Act 5 scene 1 of Arthur Golding's 1567 translation of Medea's incantation in Ovid's 7th book); Gonzalo's 'golden age' oration in Act 2 scene 1 based closely on Michel de Montaigne's essay 'Of the Cannibals', translated by John Florio (1603).
37
+ TEXT: First Folio of 1623 is the only early printed text. Based on a transcript by Ralph Crane, professional scribe working for the King's Men. Generally good quality of printing.
38
+ The Tempest
39
+ PROSPERO, the right Duke of Milan
40
+ MIRANDA, his daughter
41
+ ALONSO, King of Naples
42
+ SEBASTIAN, his brother
43
+ ANTONIO, Prospero's brother, the usurping Duke of Milan
44
+ FERDINAND, son to the King of Naples
45
+ GONZALO, an honest old councillor
46
+ ADRIAN and FRANCISCO, lords
47
+ TRINCULO, a jester
48
+ STEPHANO, a drunken butler
49
+ MASTER of a ship
50
+ BOATSWAIN
51
+ MARINERS
52
+ CALIBAN, a savage and deformed slave
53
+ ARIEL, an airy spirit
54
+ The Scene: an uninhabited island
55
+ Act 1
56
+ Scene 11running scene 1
57
+ A tempestuous noise of thunder and lightning heard. Enter a Shipmaster and a Boatswain2
58
+ MASTER Boatswain!
59
+ BOATSWAIN Here, master. What cheer3?
60
+ MASTER Good4: speak to th'mariners. Fall to't yarely5, or we run ourselves aground! Bestir6, bestir!
61
+ Exit
62
+ Enter Mariners
63
+ BOATSWAIN Heigh, my hearts7! Cheerly8, cheerly, my hearts! Yare, yare9! Take in the topsail10. Tend11 to th'master's whistle.— Blow, till thou burst thy wind, if room enough12.
64
+ To the storm
65
+ Enter Alonso, Sebastian, Antonio, Ferdinand, Gonzalo and others
66
+ ALONSO Good boatswain, have13 care. Where's the master? Play the14 men.
67
+ BOATSWAIN I pray now, keep below.
68
+ ANTONIO Where is the master, boatswain?
69
+ BOATSWAIN Do you not hear him? You mar15 our labour. Keep your cabins! You do assist the storm.
70
+ GONZALO Nay, good, be patient.
71
+ BOATSWAIN When the sea is. Hence16! What cares these roarers17 for the name of king? To cabin! Silence! Trouble us not.
72
+ GONZALO Good, yet remember whom thou hast aboard.
73
+ BOATSWAIN None that I more love than myself. You are a counsellor18: if you can command these elements to silence, and work the peace of the present19, we will not hand20 a rope more: use your authority. If you cannot, give thanks you have lived so long, and make yourself ready in your cabin for the mischance of the hour, if it so hap21.— Cheerly, good hearts!—
74
+ To the Mariners
75
+ Out of our way, I say.
76
+ To the Courtiers
77
+ Exeunt [Boatswain with Mariners, followed by Alonso, Sebastian, Antonio and Ferdinand]
78
+ GONZALO I have great comfort from this fellow: methinks he hath no drowning mark22 upon him: his complexion is perfect gallows23. Stand fast, good Fate, to his hanging: make the rope of his destiny24 our cable25, for our own doth little advantage. If he be not born to be hanged, our case is miserable.
79
+ Exit
80
+ Enter Boatswain
81
+ BOATSWAIN Down with the topmast26! Yare! Lower, lower! Bring her to try with main course27. (A cry within) A plague upon this howling! They are louder than the weather or our office28.
82
+ Enter Sebastian, Antonio and Gonzalo
83
+ Yet again? What do you here? Shall we give o'er29 and drown? Have you a mind to sink?
84
+ SEBASTIAN A pox30cur31 o'your throat, you bawling, blasphemous, incharitable dog!
85
+ BOATSWAIN Work you then.
86
+ ANTONIO Hang, cur! Hang, you whoreson, insolent noisemaker! We are less afraid to be drowned than thou art.
87
+ GONZALO I'll warrant him for drowning32, though the ship were no stronger than a nutshell and as leaky as an unstanched33 wench.
88
+ BOATSWAIN Lay her ahold34, ahold! Set her two courses off to35 sea again! Lay her off!
89
+ Enter Mariners, wet
90
+ MARINERS All lost! To prayers, to prayers! All lost!
91
+ BOATSWAIN What, must our mouths be cold36?
92
+ GONZALO The king and prince at prayers: let's assist them, for our case is as theirs.
93
+ SEBASTIAN I'm out of patience.
94
+ ANTONIO We are merely37 cheated of our lives by drunkards. This wide-chopped38 rascal: would thou mightst lie drowning, the washing of ten tides39!
95
+ GONZALO He'll be hanged yet40,
96
+ Though every drop of water swear against it
97
+ And gape at wid'st41 to glut42 him.
98
+ [Exeunt Boatswain and Mariners]
99
+ A confused noise within
100
+ [VOICES OFF-STAGE] Mercy on us! — We split43, we split! — Farewell, my wife and children! — Farewell, brother! — We split, we split, we split!
101
+ ANTONIO Let's all sink wi'th'king.
102
+ SEBASTIAN Let's take leave of him.
103
+ Exeunt[Antonio and Sebastian]
104
+ GONZALO Now would I give a thousand furlong44s of sea for an acre45 of barren ground: long heath46, brown furze47, anything. The wills above be done! But I would fain48 die a dry death.
105
+ Exit
106
+ Scene 249running scene 2
107
+ Enter Prospero50 and Miranda51
108
+ MIRANDA If by your art52, my dearest father, you have
109
+ Put the wild waters in this roar, allay53 them.
110
+ The sky, it seems, would pour down stinking pitch54,
111
+ But that the sea, mounting to th'welkin's55 cheek,
112
+ Dashes the fire56 out. O, I have suffered
113
+ With those that I saw suffer: a brave57 vessel —
114
+ Who had, no doubt, some noble creature in her —
115
+ Dashed all to pieces. O, the cry did knock
116
+ Against my very heart. Poor souls, they perished.
117
+ Had I been any god of power, I would
118
+ Have sunk the sea within the earth, or ere58
119
+ It should the good ship so have swallowed, and
120
+ The fraughting souls59 within her.
121
+ PROSPERO Be collected60:
122
+ No more amazement61. Tell your piteous heart
123
+ There's no harm done.
124
+ MIRANDA O, woe the day!
125
+ PROSPERO No harm:
126
+ I have done nothing but in care of thee —
127
+ Of thee, my dear one, thee, my daughter — who
128
+ Art ignorant of what thou art: nought knowing
129
+ Of whence I am62, nor that I am more better63
130
+ Than Prospero, master of a full poor cell64,
131
+ And thy no greater father65.
132
+ MIRANDA More to know66
133
+ Did never meddle with67 my thoughts.
134
+ PROSPERO 'Tis time
135
+ I should inform thee further. Lend thy hand
136
+ And pluck my magic garment from me. So:
137
+ Lays down his magic cloak
138
+ Lie there, my art. Wipe thou thine eyes, have comfort.
139
+ The direful spectacle of the wreck, which touched
140
+ The very virtue of compassion in thee,
141
+ I have with such provision68 in mine art
142
+ So safely ordered that there is no soul —
143
+ No, not so much perdition69 as an hair
144
+ Betid70 to any creature in the vessel
145
+ Which thou heard'st cry, which thou saw'st sink. Sit down,
146
+ Miranda sits
147
+ For thou must now know further.
148
+ MIRANDA You have often
149
+ Begun to tell me what I am, but stopped
150
+ And left me to a bootless inquisition71,
151
+ Concluding 'Stay: not yet.'
152
+ PROSPERO The hour's now come,
153
+ The very minute bids thee ope72 thine ear:
154
+ Obey, and be attentive. Canst thou remember
155
+ A time before we came unto this cell?
156
+ I do not think thou canst, for then thou wast not
157
+ Out73 three years old.
158
+ MIRANDA Certainly, sir, I can.
159
+ PROSPERO By what? By any other house or person?
160
+ Of any thing the image, tell me, that
161
+ Hath kept with thy remembrance74.
162
+ MIRANDA 'Tis far off,
163
+ And rather like a dream than an assurance75
164
+ That my remembrance warrants76. Had I not
165
+ Four or five women once that tended77 me?
166
+ PROSPERO Thou hadst; and more, Miranda. But how is it
167
+ That this lives in thy mind? What see'st thou else
168
+ In the dark backward78 and abysm79 of time?
169
+ If thou rememb'rest aught80 ere thou cam'st here,
170
+ How thou cam'st here thou mayst.
171
+ MIRANDA But that I do not.
172
+ PROSPERO Twelve year since, Miranda, twelve year since,
173
+ Thy father was the Duke of Milan and
174
+ A prince of power.
175
+ MIRANDA Sir, are not you my father?
176
+ PROSPERO Thy mother was a piece81 of virtue, and
177
+ She said thou wast my daughter; and thy father
178
+ Was Duke of Milan, and his only heir
179
+ And princess, no worse issued82.
180
+ MIRANDA O the heavens!
181
+ What foul play had we, that we came from thence?
182
+ Or blessèd83 wast we did?
183
+ PROSPERO Both, both, my girl.
184
+ By foul play — as thou say'st — were we heaved thence,
185
+ But blessedly holp84 hither.
186
+ MIRANDA O, my heart bleeds
187
+ To think o'th'teen85 that I have turned you to86,
188
+ Which is from87 my remembrance. Please you, further.
189
+ PROSPERO My brother and thy uncle, called Antonio —
190
+ I pray thee, mark88 me — that a brother should
191
+ Be so perfidious89 — he whom next thyself
192
+ Of all the world I loved, and to him put
193
+ The manage90 of my state, as at that time
194
+ Through all the signories91 it was the first,
195
+ And Prospero the prime92 duke, being so reputed
196
+ In dignity, and for the liberal arts93
197
+ Without a parallel; those being all my study,
198
+ The government I cast upon my brother
199
+ And to my state94 grew stranger95, being transported
200
+ And rapt96 in secret studies. Thy false uncle —
201
+ Dost thou attend me?
202
+ MIRANDA Sir, most heedfully.
203
+ PROSPERO Being once perfected97 how to grant suits98,
204
+ How to deny them, who t'advance and who
205
+ To trash for over-topping99, new created
206
+ The creatures that were mine100, I say, or changed 'em101,
207
+ Or else new formed 'em102; having both the key103
208
+ Of officer and office, set all hearts i'th'state
209
+ To what tune pleased his ear, that104 now he was
210
+ The ivy which had hid my princely trunk105
211
+ And sucked my verdure106 out on't.— Thou attend'st not.
212
+ MIRANDA O good sir, I do.
213
+ PROSPERO I pray thee, mark me:
214
+ I, thus neglecting worldly ends107, all dedicated
215
+ To closeness108 and the bettering of my mind
216
+ With that, which but109 by being so retired110,
217
+ O'er-prized all popular rate111, in my false brother
218
+ Awaked an evil nature, and my trust,
219
+ Like a good parent112, did beget of113 him
220
+ A falsehood in its contrary114, as great
221
+ As my trust was, which had indeed no limit,
222
+ A confidence sans115 bound. He being thus lorded116,
223
+ Not only with what my revenue yielded,
224
+ But what my power might else exact117: like one
225
+ Who having into118 truth, by telling of it119,
226
+ Made such a sinner of his memory
227
+ To credit his own lie120, he did believe
228
+ He was indeed the duke, out o'th'substitution121
229
+ And executing th'outward face122 of royalty
230
+ With all prerogative: hence his ambition growing —
231
+ Dost thou hear?
232
+ MIRANDA Your tale, sir, would cure deafness.
233
+ PROSPERO To have no screen123 between this part he played,
234
+ And him124 he played it for, he needs will be
235
+ Absolute Milan125. Me — poor man — my library
236
+ Was dukedom large enough: of temporal royalties126
237
+ He thinks me now incapable. Confederates127 —
238
+ So dry128 he was for sway129 — wi'th'King of Naples
239
+ To give him annual tribute130, do him homage,
240
+ Subject his coronet to his crown131, and bend
241
+ The dukedom yet132 unbowed — alas, poor Milan —
242
+ To most ignoble stooping.
243
+ MIRANDA O the heavens!
244
+ PROSPERO Mark his condition133 and th'event134, then tell me
245
+ If this might be a brother135.
246
+ MIRANDA I should sin
247
+ To think but136 nobly of my grandmother:
248
+ Good wombs have borne bad sons.
249
+ PROSPERO Now the condition.
250
+ This King of Naples, being an enemy
251
+ To me inveterate137, hearkens138 my brother's suit,
252
+ Which was, that he139, in lieu o'th'premises
253
+ Of homage140, and I know not how much tribute141,
254
+ Should presently extirpate142 me and mine
255
+ Out of the dukedom, and confer fair Milan,
256
+ With all the honours, on my brother: whereon,
257
+ A treacherous army levied, one midnight
258
+ Fated to th'purpose, did Antonio open
259
+ The gates of Milan, and i'th'dead of darkness
260
+ The ministers143 for th'purpose hurried thence144
261
+ Me and thy crying self.
262
+ MIRANDA Alack, for pity!
263
+ I, not rememb'ring how I cried out then,
264
+ Will cry it o'er again: it is a hint145
265
+ That wrings mine eyes to't.
266
+ PROSPERO Hear a little further,
267
+ And then I'll bring thee to the present business
268
+ Which now's upon's: without the which, this story
269
+ Were most impertinent146.
270
+ MIRANDA Wherefore did they not
271
+ That hour destroy us?
272
+ PROSPERO Well demanded, wench:
273
+ My tale provokes that question. Dear, they durst147 not,
274
+ So dear the love my people bore me: nor set
275
+ A mark so bloody on the business: but
276
+ With colours fairer, painted148 their foul ends.
277
+ In few149, they hurried us aboard a barque150,
278
+ Bore us some leagues to sea, where they prepared
279
+ A rotten carcass of a butt151, not rigged,
280
+ Nor tackle, sail, nor mast: the very rats
281
+ Instinctively have quit it. There they hoist152 us,
282
+ To cry to th'sea that roared to us; to sigh
283
+ To th'winds, whose pity sighing back again,
284
+ Did us but loving wrong153.
285
+ MIRANDA Alack, what trouble
286
+ Was I then to you!
287
+ PROSPERO O, a cherubin154
288
+ Thou wast that did preserve me. Thou didst smile,
289
+ Infusèd with a fortitude from heaven,
290
+ When I have decked155 the sea with drops full salt156,
291
+ Under my burden groaned, which157 raised in me
292
+ An undergoing stomach158, to bear up
293
+ Against what should ensue.
294
+ MIRANDA How came we ashore?
295
+ Prospero sits
296
+ PROSPERO By providence divine.
297
+ Some food we had, and some fresh water, that
298
+ A noble Neapolitan, Gonzalo,
299
+ Out of his charity — who being then appointed
300
+ Master of this design159 — did give us, with
301
+ Rich garments, linens, stuffs160 and necessaries,
302
+ Which since have steaded much161. So, of his gentleness162,
303
+ Knowing I loved my books, he furnished me
304
+ From mine own library with volumes that
305
+ I prize above my dukedom.
306
+ MIRANDA Would163 I might
307
+ But ever see that man.
308
+ PROSPERO Now I arise:
309
+ Prospero stands
310
+ Sit still164, and hear the last of our sea-sorrow.
311
+ Here in this island we arrived, and here
312
+ Have I, thy schoolmaster, made thee more profit165
313
+ Than other princes can that have more time
314
+ For vainer166 hours, and tutors not so careful167.
315
+ MIRANDA Heavens thank you for't. And now, I pray you, sir,
316
+ For still 'tis beating in my mind: your reason
317
+ For raising this sea-storm?
318
+ PROSPERO Know thus far forth:
319
+ By accident most strange, bountiful Fortune —
320
+ Now my dear lady168 — hath mine enemies
321
+ Brought to this shore: and by my prescience169
322
+ I find my zenith170 doth depend upon
323
+ A most auspicious star, whose influence171
324
+ If now I court not, but omit172, my fortunes
325
+ Will ever after droop. Here cease more questions:
326
+ Thou art inclined to sleep. 'Tis a good dullness173,
327
+ And give it way174: I know thou canst not choose.—
328
+ Miranda sleeps
329
+ Come away, servant, come. I am ready now.
330
+ Approach, my Ariel175, come.
331
+ Enter Ariel
332
+ ARIEL All hail, great master! Grave176 sir, hail! I come
333
+ To answer thy best pleasure; be't to fly,
334
+ To swim, to dive into the fire, to ride
335
+ On the curled clouds: to thy strong bidding task177
336
+ Ariel and all his quality178.
337
+ PROSPERO Hast thou, spirit,
338
+ Performed to point179 the tempest that I bade thee?
339
+ ARIEL To every article.
340
+ I boarded the king's ship: now on the beak180,
341
+ Now in the waist181, the deck, in every cabin,
342
+ I flamed amazement182: sometime I'd divide
343
+ And burn in many places; on the topmast,
344
+ The yards183 and bowsprit184 would I flame distinctly,
345
+ Then meet and join. Jove's lightning, the precursors
346
+ O'th'dreadful thunderclaps185, more momentary
347
+ And sight-outrunning186 were not; the fire and cracks
348
+ Of sulphurous roaring, the most mighty Neptune187
349
+ Seem to besiege and make his bold waves tremble,
350
+ Yea, his dread trident188 shake.
351
+ PROSPERO My brave spirit!
352
+ Who was so firm, so constant, that this coil189
353
+ Would not infect his reason?
354
+ ARIEL Not a soul
355
+ But felt a fever of the mad190 and played
356
+ Some tricks of desperation191. All but mariners
357
+ Plunged in the foaming brine and quit the vessel,
358
+ Then all afire192 with me: the king's son, Ferdinand,
359
+ With hair up-staring193 — then like reeds, not hair —
360
+ Was the first man that leaped; cried 'Hell is empty
361
+ And all the devils are here.'
362
+ PROSPERO Why, that's my spirit!
363
+ But was not this nigh194 shore?
364
+ ARIEL Close by, my master.
365
+ PROSPERO But are they, Ariel, safe?
366
+ ARIEL Not a hair perished:
367
+ On their sustaining195 garments not a blemish,
368
+ But fresher than before: and, as thou bad'st me,
369
+ In troops196 I have dispersed them 'bout the isle.
370
+ The king's son have I landed by himself,
371
+ Whom I left cooling of197 the air with sighs
372
+ In an odd angle198 of the isle, and sitting,
373
+ His arms in this sad knot199.
374
+ Folds his arms
375
+ PROSPERO Of the king's ship,
376
+ The mariners, say how thou hast disposed,
377
+ And all the rest o'th'fleet?
378
+ ARIEL Safely in harbour
379
+ Is the king's ship: in the deep nook where once
380
+ Thou call'dst me up at midnight to fetch dew200
381
+ From the still-vexed Bermudas201, there she's hid;
382
+ The mariners all under hatches202 stowed,
383
+ Who, with a charm203 joined to their suffered labour204,
384
+ I have left asleep: and for the rest o'th'fleet —
385
+ Which I dispersed — they all have met again,
386
+ And are upon the Mediterranean float205
387
+ Bound sadly home for Naples,
388
+ Supposing that they saw the king's ship wrecked
389
+ And his great person perish.
390
+ PROSPERO Ariel, thy charge
391
+ Exactly is performed; but there's more work:
392
+ What is the time o'th'day?
393
+ ARIEL Past the mid season206.
394
+ PROSPERO At least two glasses207. The time 'twixt six and now
395
+ Must by us both be spent most preciously208.
396
+ ARIEL Is there more toil? Since thou dost give me pains209,
397
+ Let me remember210 thee what thou hast promised,
398
+ Which is not yet performed me.
399
+ PROSPERO How now? Moody211?
400
+ What is't thou canst demand?
401
+ ARIEL My liberty.
402
+ PROSPERO Before the time be out212? No more!
403
+ ARIEL I prithee,
404
+ Remember I have done thee worthy service,
405
+ Told thee no lies, made thee no mistakings, served
406
+ Without or213 grudge or grumblings: thou did promise
407
+ To bate me214 a full year.
408
+ PROSPERO Dost thou forget
409
+ From what a torment I did free thee?
410
+ ARIEL No.
411
+ PROSPERO Thou dost: and think'st it much to tread the ooze
412
+ Of the salt deep215,
413
+ To run upon the sharp wind of the north,
414
+ To do me business in the veins o'th'earth
415
+ When it is baked with frost.
416
+ ARIEL I do not, sir.
417
+ PROSPERO Thou liest, malignant thing. Hast thou forgot
418
+ The foul witch Sycorax216, who with age and envy
419
+ Was grown into a hoop217? Hast thou forgot her?
420
+ ARIEL No, sir.
421
+ PROSPERO Thou hast. Where was she born? Speak: tell me.
422
+ ARIEL Sir, in Algiers218.
423
+ PROSPERO O, was she so? I must
424
+ Once in a month recount what thou hast been,
425
+ Which thou forget'st. This damned witch Sycorax,
426
+ For mischiefs manifold, and sorceries terrible
427
+ To enter human hearing, from Algiers,
428
+ Thou know'st, was banished: for one thing she did
429
+ They would not take her life219. Is not this true?
430
+ ARIEL Ay, sir.
431
+ PROSPERO This blue-eyed220 hag221 was hither brought with child222,
432
+ And here was left by th'sailors. Thou, my slave,
433
+ As thou report'st thyself, was then her servant:
434
+ And, for223 thou wast a spirit too delicate224
435
+ To act her earthy225 and abhorred commands,
436
+ Refusing her grand hests226, she did confine thee
437
+ By help of her more potent ministers227,
438
+ And in her most unmitigable228 rage,
439
+ Into a cloven229 pine, within which rift
440
+ Imprisoned thou didst painfully remain
441
+ A dozen years: within which space she died,
442
+ And left thee there, where thou didst vent thy groans
443
+ As fast as mill-wheels strike230. Then was this island —
444
+ Save for the son that she did litter231 here,
445
+ A freckled whelp232, hag-born233 — not honoured with
446
+ A human shape.
447
+ ARIEL Yes: Caliban234 her son.
448
+ PROSPERO Dull thing235, I say so: he, that Caliban
449
+ Whom now I keep in service236. Thou best know'st
450
+ What torment I did find thee in: thy groans
451
+ Did make wolves howl and penetrate the breasts
452
+ Of ever-angry bears237; it was a torment
453
+ To lay upon the damned, which Sycorax
454
+ Could not again undo. It was mine art,
455
+ When I arrived and heard thee, that made gape238
456
+ The pine and let thee out.
457
+ ARIEL I thank thee, master.
458
+ PROSPERO If thou more murmur'st239, I will rend240 an oak
459
+ And peg241 thee in his knotty entrails242 till
460
+ Thou hast howled away twelve winters.
461
+ ARIEL Pardon, master:
462
+ I will be correspondent243 to command
463
+ And do my spriting244 gently245.
464
+ PROSPERO Do so: and after two days
465
+ I will discharge246 thee.
466
+ ARIEL That's my noble master!
467
+ What shall I do? Say what? What shall I do?
468
+ PROSPERO Go make thyself like a nymph o'th'sea,
469
+ Be subject to no sight but thine and mine: invisible
470
+ To every eyeball else. Go take this shape
471
+ And hither come in't: go! Hence with diligence!
472
+ Exit [Ariel]
473
+ Awake, dear heart, awake. Thou hast slept well. Awake.
474
+ To Miranda
475
+ MIRANDA The strangeness of your story put
476
+ Heaviness247 in me.
477
+ PROSPERO Shake it off. Come on:
478
+ We'll visit Caliban, my slave, who never
479
+ Yields us kind answer.
480
+ MIRANDA 'Tis a villain248, sir, I do not love to look on.
481
+ PROSPERO But, as 'tis,
482
+ We cannot miss249 him: he does make our fire,
483
+ Fetch in our wood and serves in offices250
484
+ That profit us. What, ho! Slave! Caliban!
485
+ Thou earth251, thou! Speak!
486
+ CALIBAN There's wood enough within.
487
+ Within
488
+ PROSPERO Come forth, I say! There's other business for thee:
489
+ Come, thou tortoise! When?
490
+ Enter Ariel like a water-nymph
491
+ Fine apparition: my quaint252 Ariel,
492
+ Hark in thine ear.
493
+ ARIEL My lord, it shall be done.
494
+ Exit
495
+ PROSPERO Thou poisonous slave, got253 by the devil himself
496
+ Upon thy wicked dam254: come forth!
497
+ Enter Caliban
498
+ CALIBAN As wicked dew as e'er my mother brushed
499
+ With raven's feather from unwholesome fen255
500
+ Drop on you both! A southwest256 blow on ye
data/shakespeare_zh500.txt ADDED
@@ -0,0 +1,500 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 总目录
2
+ 暴风雨莎士比亚全集·英汉双语本
3
+ 维洛那二绅士莎士比亚全集·英汉双语本
4
+ 快乐的温莎巧妇莎士比亚全集·英汉双语本
5
+ 一报还一报莎士比亚全集·英汉双语本
6
+ 错误的喜剧莎士比亚全集·英汉双语本
7
+ 无事生非莎士比亚全集·英汉双语本
8
+ 爱的徒劳莎士比亚全集·英汉双语本
9
+ 仲夏夜之梦莎士比亚全集·英汉双语本
10
+ 威尼斯商人莎士比亚全集·英汉双语本
11
+ 皆大欢喜莎士比亚全集·英汉双语本
12
+ 驯悍记莎士比亚全集·英汉双语本
13
+ 终成眷属莎士比亚全集·英汉双语本
14
+ 第十二夜莎士比亚全集·英汉双语本
15
+ 冬天的故事莎士比亚全集·英汉双语本
16
+ 特洛伊罗斯与克瑞西达莎士比亚全集·英汉双语本
17
+ 科利奥兰纳斯莎士比亚全集·英汉双语本
18
+ 泰特斯·安德洛尼克斯莎士比亚全集·英汉双语本
19
+ 罗密欧与朱丽叶莎士比亚全集·英汉双语本
20
+ 雅典的泰门莎士比亚全集·英汉双语本
21
+ 尤力乌斯·凯撒莎士比亚全集·英汉双语本
22
+ 麦克白莎士比亚全集·英汉双语本
23
+ 哈姆莱特莎士比亚全集·英汉双语本
24
+ 李尔王莎士比亚全集·英汉双语本
25
+ 奥瑟罗莎士比亚全集·英汉双语本
26
+ 安东尼与克莉奥佩特拉莎士比亚全集·英汉双语本
27
+ 辛白林莎士比亚全集·英汉双语本
28
+ 约翰王莎士比亚全集·英汉双语本
29
+ 理查二世莎士比亚全集·英汉双语本
30
+ 亨利四世上莎士比亚全集·英汉双语本
31
+ 亨利四世下莎士比亚全集·英汉双语本
32
+ 亨利五世莎士比亚全集·英汉双语本
33
+ 亨利六世上莎士比亚全集·英汉双语本
34
+ 亨利六世中莎士比亚全集·英汉双语本
35
+ 亨利六世下莎士比亚全集·英汉双语本
36
+ 理查三世莎士比亚全集·英汉双语本
37
+ 亨利八世莎士比亚全集·英汉双语本
38
+ 泰尔亲王佩力克里斯莎士比亚全集·英汉双语本
39
+ 两贵亲莎士比亚全集·英汉双语本
40
+ 莎士比亚诗集莎士比亚全集·英汉双语本
41
+ 本书版权由外语教学与研究出版社独家所有。如未获得该社书面同意书中任何部分之文字及图片不得用任何方式抄袭、节录、翻印或存储利用于任何数据库及检索系统等。
42
+ Beijing, China 100089
43
+ 京权图字01-2015-5979
44
+ 图书在版编目CIP数据
45
+ 暴风雨英汉对照英莎士比亚Shakespeare, W.著彭镜禧译—北京外语教学与研究出版社2016.3
46
+ 莎士比亚全集·英汉双语本辜正坤等主编
47
+ 书名原文The Tempest
48
+ I①暴… II①莎… ②彭… III①英语汉语对照读物 ②多幕剧剧本英国中世纪 IV① H319.4I
49
+ 中国版本图书馆CIP数据核字2016第055784号
50
+ 出版人 蔡剑峰
51
+ 项目负责 姚 虹 李 云
52
+ 责任编辑 文雪琴
53
+ 封面设计 奇文云海 设计顾问
54
+ 出版发行 外语教学与研究出版社
55
+ 社 址 北京市西三环北路19号100089
56
+ 网 址 http://www.fltrp.com
57
+ 版 次 2016年4月第1版
58
+ 书 号 ISBN 978-7-5135-7223-1
59
+ 凡侵权、盗版书籍线索请联系我社法律事务部
60
+ 举报电话01088817519
61
+ 电子邮箱banquan@fltrp.com
62
+ 法律顾问立方律师事务所 刘旭东律师
63
+ 中咨律师事务所 殷 斌律师
64
+ 目 录
65
+ 出版说明
66
+ 莎士比亚诗体重译集序
67
+ 《暴风雨》导言
68
+ 暴风雨
69
+ 宁静中的暴风雨——译后记
70
+ 返回总目录
71
+ ·1623年历史上第一部《莎士比亚全集》——著名的第一对开本First Folio由莎士比亚的演员同僚们结集出版。
72
+ ·2007年英国皇家莎士比亚剧团Royal Shakespeare Company邀约当今世界顶级莎学专家乔纳森·贝特Jonathan Bate和埃里克·拉斯姆森Eric Rasmussen对第一对开本进行了三百多年来的首次全面修订推出了新版《莎士比亚全集》。
73
+ ·2015年外语教学与研究出版社以上述新版《莎士比亚全集》为蓝本特邀当今华语翻译界和莎学界知名学者将流传下来的莎士比亚全部作品进行全新重译遂有此集。
74
+ 出版说明
75
+ 1623年莎士比亚的演员同僚们倾注心血结集出版了历史上第一部《莎士比亚全集》——著名的第一对开本这是三百多年来许多导演和演员最为钟爱的莎士比亚文本。2007年由英国皇家莎士比亚剧团Royal Shakespeare Company推出的《莎士比亚全集》则是对第一对开本首次全面的修订。
76
+ 本套《莎士比亚全集》新汉译本正是依据当今莎学界最负声望的皇家版《莎士比亚全集》翻译而成。为了让读者在阅读译本的时候也能够了解到原版的辑注风格与成果也为了方便对照查阅出版者在版式呈现上尽量遵照原版译本的凡例说明如下
77
+ 一、文体剧文有诗体和散体之分。在英文行文中诗行的标志是未及最右行末即转行且每行的首字母大写。文字连排直至最右行末转行的则为散体。中文译文对此均遵照原版处理。
78
+ 二、舞台提示
79
+ 1角色的上场与下场。在对开本中角色的上场、下场标示比较完备原版编辑者亦尽量忠实地予以了保留。在缺漏或需作订正的地方以方括号进行标注如[and Attendants]。中文译文在处理上对应英文保留了同样的标注如[及众侍从]。
80
+ 2其他舞台提示。表示其他舞台活动、改变说活对象、旁白等的舞台提示在对开本中很少出现大多为当代编辑者所添加。皇家版编辑者试图将这类指导性的directorial提示与对开本式的Folio-style提示区分开来前者置于每页最右侧采用了另一种字体当然对这种提示类型的判断存在主观的因素。有时亦有不确定的情形出现于是编辑者给予了允许选择的提示如Aside旁白表示某行剧文既可作为旁白亦可当作对话又如某个舞台活动置于箭头↓↓之间表示它可发生在一场戏中的多个不同时刻。中文译文亦遵照原版处理。
81
+ 愿广大读者在品味译者的佳文时亦体验到辑注的精审想必会有一番意想不到的新收获。
82
+ 莎士比亚诗体重译集序
83
+ 辜正坤
84
+ 他非一代骚人实属万古千秋。
85
+ 这是英国大作家本·琼森Ben Jonson在第一部《莎士比亚全集》Mr. William Shakespeares Comedies, Histories, & Tragedies, 1623扉页上题诗中的诗行。三百多年来莎士比亚在全球逐步成为一个家喻户晓的名字似乎与这句预言在在呼应。但这并非偶然言中有许多因素可以解释莎士比亚这一巨大的文化现象产生的必然性。最关键的至少有下面几点。
86
+ 首先其作品内容具有惊人的多样性。世界上很难有第二个作家像莎士比亚这样能够驾驭如此广阔的题材。他的作品内容几乎无所不包称得上英国社会的百科全书。帝王将相、走卒凡夫、才子佳人、恶棍屠夫……一切社会阶层都展现于他的笔底。从海上到陆地从宫廷到民间从国际到国内从灵界到凡尘……笔锋所指无处不至。悲剧、喜剧、历史剧、传奇剧叙事诗、抒情诗……都成为他显示天才的文学样式。从哲理的韵味到浪漫的爱情从盘根错节的叙述到一唱三叹的诗思波涛汹涌的情怀妙夺天工的笔触凡开卷展读者无不为之拊掌称绝。即使只从莎士比亚使用过的海量英语词汇来看也令人产生仰之弥高的感觉。德国语言学家马克斯·缪勒Max Müller原以为莎士比亚使用过的词汇最多为15,000个事后证明这当然是小看了语言大师的词汇储藏量。美国教授爱德华·霍尔登Edward Holden经过一番考察后认为至少达24,000个。可是他哪里知道这依然是一种低估。有学者甚至声称用电脑检索出莎士比亚用的词汇多达43,566个当然这些数据还不是莎士比亚作品之所以产生空前影响的关键因素。
87
+ 其次但也许是更重要的原因他的作品具有极高的娱乐性。文学作品的生命力在于它能寓教于乐。莎士比亚的作品不是枯燥的说教而是能够给予读者或观众极大艺术享受的娱乐性创造物往往具有明显的煽情效果有意刺激人的欲望。这种艺术取向当然不是纯粹为了娱乐而娱乐掩藏在背后的是当时西方人强有力的人本主义精神即用以人为本的价值观来对抗欧洲上千年来以神为本的宗教价值观。重欲望、重娱乐的人本主义倾向明显对重神灵、重禁欲的神本主义产生了极大的挑战。当然莎士比亚的人本主义与中国古人所主张的人本主义有很大的区别。要而言之前者在相当大的程度上肯定了人的本能欲望或原始欲望的正当性而后者则主要强调以人的仁爱为本规范人类社会秩序的高尚的道德要求。二者都具有娱乐效果但前者具有纵欲性或开放性娱乐效果后者则具有节欲性或适度自律性娱乐效果。换句话说对于16、17世纪的西方人来说莎士比亚的作品暗中契合了试图挣脱过分禁欲的宗教教义的约束而走向个性解放的千百万西方人的娱乐追求因此它会取得巨大成功是势所必然的。
88
+ 第三时势造英雄。人类其实从来不缺善于煽情的作手或视野宏阔的巨匠缺的常常是时势和机遇。莎士比亚的时代恰恰是英国文艺复兴思潮达到鼎盛的时代。禁欲千年之久的欧洲社会如堤坝围裹的宏湖表面上浪静风平其底层却汹涌着决堤的纵欲性暗流。一旦湖堤洞开飞涛大浪呼卷而下浩浩汤汤汇作长河而莎士比亚恰好是河面上乘势而起的弄潮儿其迎合西方人情趣的精湛表演遂赢得两岸雷鸣般的喝彩声。时势不光涵盖社会发展的总趋势也牵连着别的因素。比如说文学或文化理论界、政治意识形态对莎士比亚作品理解、阐释的多样性与莎士比亚作品本身内容的多样性产生相辅相成的效果。“说不尽的莎士比亚”成了西方学术界的口头禅。西方的每一种意识形态理论尤其是文学理论要想获得有效性都势必会将阐释莎士比亚的作品作为试金石。17世纪初的人文主义18世纪的启蒙主义19世纪的浪漫主义20世纪的现实主义或批判现实主义都不同程度地、选择性地把莎士比亚作品作为阐释其理论特点的例证。也许17世纪的古典主义曾经阻遏过西方人对莎士比亚作品的过度热情但是19世纪的浪漫主义流派却把莎士比亚作品推崇到无以复加的崇高地位莎士比亚俨然成了西方文学的神灵。20世纪以来西方资本主义阵营和社会主义阵营可以说在意识形态的各个方面都互相对立势同水火可是在对待莎士比亚的问题上居然有着惊人的共识与默契。不用说社会主义阵营的立场与社会主义理论的创始者马克思Karl Marx、恩格斯Friedrich Engels个人的审美情趣息息相关。马克思一家都是莎士比亚的粉丝马克思称莎士比亚为“人类最伟大的天才之一人类文学奥林波斯山上的宙斯”他号召作家们要更加莎士比亚化。恩格斯甚至指出“单是《温莎的风流娘儿们》的第一幕就比全部德国文学包含着更多的生活气息。”不用说这些话多多少少有某种程度的文学性夸张但对莎士比亚的崇高地位来说却无疑产生了极大的推动作用。
89
+ 第四1623年版《莎士比亚全集》奠定莎士比亚崇拜传统。这个版本即眼前译本所依据的皇家版《莎士比亚全集》The RSC William Shakespeare: Complete Works, 2007的主要内容。该版本产生于莎士比亚去世的第七年。莎士比亚的舞台同仁赫明奇John Heminge和康德尔Henry Condell整理出版了第一部莎士比亚戏剧集。当时的大学者、大作家本·琼森为之题诗诗中写道“他非一代骚人实属万古千秋。”这个调子奠定了莎士比亚偶像崇拜的传统。而这个传统一旦形成后人就难以反抗。英国文学中的莎士比亚偶像崇拜传统已经形成了一种自我完善、自我调整、自我更新的机制。至少近两百年来莎士比亚的文学成就已被宣传成世界文学的顶峰。
90
+ 第五现在署名“莎士比亚”的作品很可能不只是莎士比亚一个人的成果而是凝聚了当时英国若干戏剧创作精英的团体努力。众多大作家的智慧浓缩在以“莎士比亚”为代号的作品集中其成就的伟大性自然就获得了解释。当然这最后一点只是莎士比亚研究界若干学者的研究性推测远非定论。有的莎士比亚著作爱好者害怕一旦证明莎士比亚不是署名为“莎士比亚”的著作的作者莎士比亚的著作便失去了价值这完全是杞人忧天。道理很简单人们即使证明了《红楼梦》的作者不是曹雪芹或《三国演义》的作者不是罗贯中也丝毫不影响这些作品的伟大价值。同理人们即使证明了《莎士比亚全集》不是莎士比亚一个人创作的也丝毫不会影响《莎士比亚全集》是世界文学中的伟大作品这个事实反倒会更有力地证明这个事实因为集体的智慧远胜于个人。
91
+ 皇家版《莎士比亚全集》译本翻译总思路
92
+ 横亘于前的这套新译本是依据当今莎学界最负声望的皇家版《莎士比亚全集》进行翻译的而皇家版又正是以本·琼森题过诗的1623年版《莎士比亚全集》为主要依据。
93
+ 这套译本是在考察了中国现有的各种译本后根据新的历史条件和新的翻译目的打造出来的。其总的翻译思路是本套译本主编会同外语教学与研究出版社的相关领导和责任编辑讨论的结果。总起来说皇家版《莎士比亚全集》译本在翻译思路上主要遵循了以下几条
94
+ 1版本依据。如上所述本版汉译本译文以英国皇家版《莎士比亚全集》为基本依据。但在翻译过程中译者亦酌情参阅了其他版本以增进对原作的理解。
95
+ 2翻译内容包括内页所含全部文字。例如作品介绍与评论、正文、注释等。
96
+ 3注释处理问题。对于注释的处理1翻译时如果正文译文已经将英文版某注释的基本含义较准确地表达出来了则该注释即可取消2如果正文译文只是部分地将英文版对应注释的基本含义表达出来则该注释可以视情况部分或全部保留3如果注释本身存疑可以在保留原注的情况下加入译者的新注。但是所加内容务必有理有据。
97
+ 4翻译风格问题。对于风格的处理1在整体风格上译文应该尽量逼肖原作整体风格包括以诗体译诗体以散体译散体2版式风格亦尽量保留例如页边行号数码亦应在译文中保留俾便读者索查原文3在具体的文字传输处理上通常应该注重汉译本身的文字魅力增强汉译本的可读性。不宜太白话不宜太文言文白用语宜尽量自然得体。句子不要太绕注意汉语自身表达的句法结构尤其是其逻辑表达方式。意义的异化性不等于文字形式本身的异化性因此要注意用汉语的归化性来传输、保留原作含义的异化性。朱生豪先生的译本语言流畅、可读性强但可惜不是诗体有违原作形式。当下译本是要在承传朱先生译本优点的基础上根据新时代的读者审美趣味取得新的���展。梁实秋先生等的译本在达意的准确性上比朱译有所进步也是我们应该吸纳的优点。但是梁译文采不足则须注意避其短。方平先生等的译本也把莎士比亚翻译往前推进了一步在进行大规模诗体翻译方面作出了宝贵的尝试但是离真正的诗体尚有距离。此外前此的所有译本对于莎士比亚原作的色情类用语都有程度不同的忽略本套皇家版译本则尽力在此方面还原莎士比亚的本真状态论述见后文。其他还有一些译本亦都应该受到我们的关注处理原则类推。每种译本都有自己独特的东西。我们希望美的译文是这套译本的突出特点。
98
+ 5借鉴他种汉译本问题。凡是我们曾经参考过的较好的译本都在适当的地方加以注明承认前辈译者的功绩。借鉴利用是完全必要的但是要正大光明避免暗中抄袭。
99
+ 6具体翻译策略问题特别关键下文将其单列进行陈述。
100
+ 莎士比亚作品翻译领域大转折真正的诗体译本
101
+ 莎士比亚首先是一个诗人。莎士比亚的作品基本上都以诗体写成。因此要想尽可能还原本真的莎士比亚就必须将莎士比亚作品翻译成为诗体而不是散文这在莎学界已经成为共识。但是紧接而来的问题是什么叫诗体或需要什么样的诗体
102
+ 按照我们的想法1所谓诗体首先是措辞上的诗味必须尽可能浓郁2节奏上的诗味包括分行等要予以高度重视3结合中国人的审美习惯剧文可以押韵也可以不押韵。但不押韵的剧文首先要满足前两个要求。
103
+ 本全集翻译原计划由笔者一个人来完成。但是莎士比亚的创作具有惊人的多样性其作品来源也明显具有莎士比亚时代若干其他作家与作品的痕迹因此完全由某一个译者翻译成一种风格也许难免偏颇难以和莎士比亚风格的多样性相呼应。所以集众人的力量来完成大业应该更加合理更加具有可操作性。
104
+ 具体说来新时代提出了什么要求简而言之就是用真正的诗体翻译莎士比亚的诗体剧文。这个任务是朱生豪先生无法完成的。朱先生说过他在翻译莎士比亚作品时“当然预备全部用散文译出否则将要了我的命”。1显然朱先生也考虑过用诗体来翻译莎士比亚著作的问题但是他的结论是第一靠单独一个人用诗体翻译《莎士比亚全集》是办不到的会因此累死第二他用散文翻译也是不得已的办法因为只有这样他才有可能在有生之年完成《莎士比亚全集》的翻译工作。
105
+ 将《莎士比亚全集》翻译成诗体比翻译成散文体要难得多。难到什么程度呢和朱生豪先生的翻译进度比较一下就知道了。朱先生翻译得最快的时候一天可以翻译一万字。2为什么会这么快朱先生才华过人这当然是一个因素但关键因素是他是用散文翻译的。用真正的诗体就不一样了。以笔者自己的体验今日照样用散文翻译莎士比亚剧本最快时也可达到每日一万字。这是因为今日的译者有比以前更完备的注释本和众多的前辈汉译本作参考至少在理解原著时要比朱先生当年省力得多所以翻译速度上最高达到一万字是不难的。但是翻译成诗体就是另外一回事了。这比自己写诗还要难得多。写诗是自己随意发挥译诗则必须按照别人的意思发挥等于是戴着镣铐跳舞。笔者自己写诗诗兴浓时一天数百行都可以写得出来但是翻译诗一天只能是几十行统计成字数往往还不到一千字最多只是朱生豪先生散文翻译速度的十分之一。梁实秋先生翻译《莎士比亚全集》用的也是散文但是也花了37年如果要翻译成真正的诗体那么至少得370年由此可见真正的诗体《莎士比亚全集》汉译本的诞生有多么艰难。此次笔者约稿的各位译者都是用诗体翻译并且都表示花费了大量的时间皇家版《莎士比亚全集》译本凝聚了诸位译者的多少努力也就不言而喻了。
106
+ 翻译诗体分辨不是分了行就是真正的诗
107
+ 主张将莎士比亚剧作翻译成诗体成了共识但是什么才是诗体却缺乏共识。在白话诗盛行的时代许多人只是简单地认定分了行的文字就是诗这个概念。分行只是一个初级的现代诗要求甚至不必是必然要求因为有些称为诗的文字甚至连分行形式都没有。不过在莎士比亚作品的翻译上要让译文具有诗体的特征首先是必定要分行的因为莎士比亚原作本身就有严格的分行形式。这个不用多说。但是译文按莎士比亚的方式分了行只是达到了一个初级的低标准。莎士比亚的剧文读起来像不像诗还大有讲究。
108
+ 卞之琳先生对此是颇有体会的。他的译本是分行式诗体但是他自己也并不认为他译出的莎士比亚剧本就是真正的诗体译本。他说读者阅读他的译本时“如果……不感到是诗体不妨就当散文读就用散文标准来衡量”。3这是一���诚实的译者说出的诚实话。不过卞先生很谦虚他有许多剧文其实读起来还是称得上诗体的。原因是什么原因是他注意到了笔者上文提到的两点第一诗的措辞第二诗的节奏。只不过他迫于某些客观原因并没有自始至终侧重这方面的追求而已。
109
+ 显然一些译本翻译了莎士比亚的剧文在行数上靠近莎士比亚原作措辞也还流畅。这些是不是就是理想的诗体莎士比亚译本呢笔者认为这还不够。什么是诗对于中国人来说有几千年的历史我们不能脱离这个悠久的传统来讨论这个问题。为此我们不得不重新提到一些基本概念什么是诗什么是诗歌翻译
110
+ 诗歌是语言艺术诗歌翻译也就必须是语言艺术
111
+ 讨论诗歌翻译必须从讨论诗歌开始。
112
+ 诗主情。诗言志。诚然。但诗歌首先应该是一种精妙的语言艺术。同理诗歌的翻译也就不得不首先表现为同类精妙的语言艺术。若译者的语言平庸而无光彩与原作的语言艺术程度差距太远那就最多只是原诗含义的注释性文字算不得真正的诗歌翻译。
113
+ 那么何谓诗歌的语言艺术
114
+ 无他修辞造句、音韵格律一整套规矩而已。无规矩不成方圆无限制难成大师。奥运会上所有的技能比赛无不按照特定的规矩来显示参赛者高妙的技能。德国诗人歌德Johann Wolfgang von Goethe《自然和艺术》“Natur und Kunst”一诗最末两行亦彰扬此理
115
+ 非限制难见作手
116
+ 唯规矩予人自由。4
117
+ 艺术家的“自由”得心应手之谓也。诗歌既为语言艺术自然就有一整套相应的语言艺术规则。诗人应用这套规则时一旦达到得心应手的程度那就是达到了真正成熟的境界。当然规矩并非一点都不可打破但只有能够将规矩使用到随心所欲而不逾矩的程度的人才真正有资格去创立新规矩丰富旧规矩。创新是在承传旧规则长处的基础上来进行的而不是完全推翻旧规则肆意妄为。事实证明在语言艺术上凡无视积淀千年的诗歌语言规则随心所欲地巧立名目、乱行胡来者永不可能在诗歌语言艺术上取得大的成就所以歌德认为
118
+ 若徒有放任习性
119
+ 则永难至境遨游。5
120
+ 诗歌语言艺术如此需要规则如此不可放任不羁诗歌的翻译自然也同样需要相类似的要求。这个要求就是笔者前面提出的主张若原诗是精妙的语言艺术则理论上说来译诗也应是同类精妙的语言艺术。
121
+ 但是“同类”绝非“同样”。因为由于原作和译作使用的语言载体不一样其各自产生的语言艺术规则和效果也就各有各的特点大多不可同样复制、照搬。所以译作的最高目标是尽可能在译入语的语言艺术领域达到程度大致相近的语言艺术效果。这种大致相近的艺术效果程度可叫作“最佳近似度”。它实际上也就是一种翻译标准只不过针对不同的文类最佳近似度究竟在哪些因素方面可最佳程度地并不一定是最大程度地取得近似效果不是一成不变的而是具有高度的灵活性。不同的文类甚至针对不同的受众我们都可以设定不同的最佳近似度。这点在拙著《中西诗比较鉴赏与翻译理论》清华大学出版社2010年的相关章节中有详细的厘定此不赘。
122
+ 话与诗的关系话不是诗
123
+ 古人的口语本来就是白话与现在的人说的口语是白话一个道理。
124
+ 正因为白话太俗不够文雅古人慢慢将白话进行改进使它更加规范、更加准确并且用语更加丰富多彩于是文言产生。在文言的基础上还有更文的文字现象那就是诗歌于是诗歌产生。所以就诗歌而言文言味实际上就是一种特殊的诗味。文言有浅近的文言也有佶屈聱牙的文言。中国传统诗歌绝大多数是浅近的文言但绝非口语、白话。诗中有话的因素自不待言但话的因素往往正是诗试图抑制的成分。
125
+ 文言和诗歌的产生是低俗的口语进化到高雅、准确层次的标志。文言和诗歌的进一步发展使得语言的艺术性愈益增强。最终文言和诗歌完成了艺术性语言的结晶化定型。这标志着古代文学和文学语言的伟大进步。《诗经》、楚辞、唐诗、宋词、元明戏曲以及从先秦、汉、唐、宋、元至明清的散文等都是中国语言艺术逐步登峰造极的明证。
126
+ 人们往往忘记话不是诗诗是话的升华。话据说至少有几十万年的历史而诗却只有几千年的历史。白话通过漫长的岁月才升华成了诗。因此从理论上说白话诗不是最好的诗而只是低层次的、初级的诗。当一行文字写得不像是话时它也许更像诗。“太阳落下山去了”是话硬说它是诗也只是平庸的诗人人可为。而同样含义的“白日依山尽”不像是话却是真正的诗非一般人可为只有诗人才写得出。它的语言表达方式与一般人的通用白话脱离开来了实现了与通用语的偏离deviation from the norm。这里的通用语指人们天天使用的白话。试想把唐诗宋词译成白话还有多少诗味剩下来
127
+ 谢谢古代先辈们一代又一代、不屈不挠的努力话终于进化成了诗。
128
+ 但是20世纪初一些激进的中国学者鼓荡起一场声势浩大的白话文运动。
129
+ 客观说来用白话文来书写、阅读自然科学和人文科学文献例如哲学、政治学、伦理学、经济学等等文献这都是伟大的进步。这个进步甚至可以上溯到八百多年前朱熹等大学者用白话体文章传输理学思想。对此笔者非常拥护非常赞成。
130
+ 但是约一百年前的白话诗运动却未免走向了极端事实上是一种语言艺术方面的倒退行为。已经高度进化的诗词曲形式被强行要求返祖回归到三千多年前的类似白话的状态已经高度语言艺术化了的诗被强行要求退化成话。艺术性相对较低的白话反倒成了正统艺术性较高的诗反倒成了异端。其实容许口语类白话诗和文言类诗并存这才是正确的选择。但一些激进学者故意拔高白话地位在诗歌创作领域搞成白话至上主义这就走上了极端主义道路。
131
+ 这个运动影响到诗歌翻译的结果是什么呢结果是西方所有的大诗人不论是古代的还是近代的如荷马Homer、但丁Dante、莎士比亚、歌德、雨果Victor Hugo、普希金Alexander Pushkin……都莫名其妙地似乎用同一支笔写出了20世纪初才出现的味道几乎相同的白话文汉诗
132
+ 将产生这种极端性结果的原因再回推我们会清楚地明白当年的某些学者把文学艺术简单雷同于人文社会科学误解了文学艺术尤其是诗歌艺术的特殊性质误以为诗就是话混淆了诗与话的形式因素。
133
+ 针对莎士比亚戏剧诗的翻译对策
134
+ 由上可知莎士比亚的剧文既然大多是格律诗无论有韵无韵它们都是诗都有格律性。因此在汉译中我们就有必要显示出它具有格律性而这种格律性就是诗性。
135
+ 问题在于格律性是附着在语言形式上的语言改变了附着其上的格律性也就大多会消失。换句话说格律大多不可复制或模仿这就正如用钢琴弹不出二胡的效果用古筝奏不出黑管的效果一样。但是原作的内在旋律是可以模仿的只是音色变了。原作的诗性是可以换个形式营造的这就是利用汉语本身的语言特点营造出大略类似的语言艺术审美效果。
136
+ 由于换了另外一种语言媒介原作的语音美设计大多已经不能照搬、复制甚至模拟了那么我们就只好断然舍弃掉原作的许多语音美设计而代之以译入语自身的语言艺术结构产生的语音美艺术设计。当然原作的某些语音美设计还是可以尝试模拟保留的但在通常的情况下大多数的语音美已经不可能传输或复制了。
137
+ 利用汉语本身的语音审美特点来营造莎士比亚诗歌的汉译语音审美效果是莎士比亚作品翻译的一个有效途径。机械照搬原作的语音审美模式多半会失败并且在大多数的场合下也没有必要。
138
+ 具体说来这就涉及翻译莎士比亚戏剧作品时该如何处理1节奏2韵律3措辞。笔者主张在这三个方面我们都可以适当借鉴利用中国古代词曲体的某些因素。戏剧剧文中的诗行一般都不宜多用单调的律诗和绝句体式。元明戏剧为什么没有采用前此盛行的五言或七言诗行而采用了长短错杂、众体皆备的词曲体这是一种艺术形式发展的必然。元明曲体由于要更好更灵活地满足抒情、叙事、论理等诸多需要故借用发展了词的形式但不是纯粹的词而是融入了民间语汇。词这种形式涵盖了一言、二言、三言、四言、五言、六言、七言、八言……乃至十多言的长短句式因此利于表达变化莫测的情、事、理。从这个意义上看莎士比亚剧文语言单位的参差不齐状态与中文词曲体句式的参差不齐状态正好有某种相互呼应的效果。
139
+ 也许有人说莎士比亚的剧文虽然是格律诗但并不怎么押韵因此汉诗翻译也就不必押韵。这个说法也有一定道理但是道理并不充实。
140
+ 首先我们应该明白既然莎士比亚的剧文是诗体人们读到现今的散体译文或不押韵的分行译文却难以感受到其应有的诗歌风味原因即在于其音乐性太弱。如果人们能够照搬莎士比亚素体诗所惯常用的音步效果及由此引起的措辞特点当然更好。但事实上原作的节奏效果是印欧语系语言本身的效果换了一种语言其效果就大多不能搬用了所以我们只好利用汉语本身的优势来创造新的音乐美。这种音乐美很难说是原作的音乐美但是它毕竟能够满足一点即诗体剧文应该具有诗歌应有的音乐美这个起码要求。而汉译的押韵可以强化这种音乐美。
141
+ 其次莎士比亚的剧文不押韵是由诸多因素造成的。第一属于印欧语系语言的英语在押韵方面存在先天的多音节不规则形���缺陷导致押韵词汇范围相对较窄。所以对于英国诗人来说很苦于押韵难工莎士比亚的许多押韵体诗例如十四行诗在押韵方面都不很工整。其次莎士比亚的剧文虽不押韵却在节奏方面十分考究这就弥补了音韵方面的不足。第三莎士比亚的剧文几乎绝大多数是诗行对于剧作者来说每部长达两三千行的诗行行都要押韵这是一个极大的挑战很难完成。而一旦改用素体剧作者便会轻松得多。但是以上几点对于汉语译本则不是一个问题。汉语的词汇及语音构成方式决定了它天生就是一种有利于押韵的艺术性语言。汉语存在大量同韵字押韵是一件很容易的事情。汉语的语音音调变化也比莎士比亚使用的英语的音调变化空间大一倍以上。汉语音调至少有四种加上轻重变化可达六至八种而英语的音调主要局限于轻重语调两种所以存在于印欧语系文字诗歌中的频频押韵有时会产生的单调感在汉语中会在很大程度上由于语调的多变而得到缓解。故汉语戏剧剧文在押韵方面有很大的潜在优势空间实际上元明戏剧剧文频频押韵就是证明。
142
+ 第三莎士比亚的剧文虽然很多不押韵但却具极强的节奏感。他惯用的格律多半是抑扬格五音步iambic pentameter诗行。如果我们在节奏方面难以传达原作的音美或者可以通过韵律的音美来弥补节奏美的丧失这种翻译对策谓之堤内损失堤外补亦谓失之东隅收之桑榆。我们的语言在某方面有缺陷可以通过另一方面的优点来弥补。当然笔者主张在一定程度上借鉴利用传统词曲的风味却并不主张使用宋词、元曲式的严谨格律而只是追求一种过分散文化和过分格律化之间的妥协状态。有韵但是不严格要适当注意平仄但不过多追求平仄效果及诗行的整齐与否不必有太固定的建行形式只是根据诗歌本身的内容和情绪赋予适当的节奏与韵式。在措辞上则保持与白话有一段距离但是绝非佶屈聱牙的文言而是趋近典雅、但普通读者也能读懂的语言。
143
+ 最后根据翻译标准多元互补论原理由于莎士比亚作品在内容、形式及审美效应方面具有多样性因此只用一种类乎纯诗体译法来翻译所有的莎士比亚剧文也是不完美的因为单一的做法也许无形中堵塞了其他有益的审美趣味通道。因此这套译本的译风虽然整体上强调诗化、诗味但是在营造诗味的途径和程度上不是单一的。我们允许诗体译风的灵活性和创新性。多译者译法实际上也是在探索诗体译法的诸多可能性这为我们将来进一步改进这套译本铺垫了一条较宽的道路。因此译文从严格押韵、半押韵到不押韵的各个程度译本都有涉猎。但是无论是否押韵其节奏和措辞应该总是富于诗意这个要求则是统一的。这是我们对皇家版《莎士比亚全集》译本的语言和风格要求。不能说我们能完全达到这个目标但我们是往这个方向努力的。正是这样的努力使这套译本与前此译本有很大的差异在一定的意义上来说标志着中国莎士比亚著作翻译的一次大转折。
144
+ 翻译突破还原莎士比亚作品禁忌区域
145
+ 另有一个课题是中国学者从前讨论得比较少的禁忌领域即莎士比亚著作中的性描写现象。
146
+ 许多西方学者认为莎士比亚酷爱色情字眼他的著作渗透着性描写、性暗示。只要有机会他就总会在字里行间用上与性相联系的双关语。西方人很早就搜罗莎士比亚著作的此类用语编纂了莎士比亚淫秽用语词典。这类词典还不止一种。1995年我又看到弗朗基·鲁宾斯坦Frankie Rubinstein等编纂了《莎士比亚性双关语释义词典》A Dictionary of Shakespeare's Sexual Puns and Their Significance厚达372页。
147
+ 赤裸裸的性描写或过多的淫秽用语在传统中国文学作品中是受到非议的尽管有《金瓶梅》这样被判为淫秽作品的文学现象但是中国传统的主流舆论还是抑制这类作品的。莎士比亚的作品固然不是通常意义上的淫秽作品但是它的大量实际用语确实有很强的色情味。这个极鲜明的特点恰恰被前此的所有汉译本故意掩盖或在无意中抹杀掉。莎士比亚的所有汉译者尤其是像朱生豪先生这样的译者显然不愿意中国读者看到莎士比亚的文笔有非常泼辣的大量使用性相关脏话的特点。这个特点多半都被巧妙地漏译或改译。于是出现一种怪现象莎士比亚著作中有些大段的篇章变成汉语后尽管读起来是通顺的读者对这些话语却往往感到莫名其妙。以《罗密欧与朱丽叶》第一幕第一场前面的30行台词为例这是凯普莱特家两个仆人山普孙与葛莱古里之间的淫秽对话。但是读者阅读过去的汉译本时很难看到他们是在说淫秽的脏话甚至会认为这些对话只是仆人之间的胡话没有什么���义。
148
+ 不过前此的译本对这类用语和描写的态度也并不完全一样而是依据年代距离在逐步改变。朱生豪先生的译本对这些东西删除改动得最多梁实秋先生已经有所保留但还是有节制。方平先生等的译本保留得更多一些但仍然持有相当的保留态度。此外从英语的不同版本看有的版本注释得明白有的版本故意模糊有的版本注释者自己也没有弄懂这些双关语那就更别说中国译者了。
149
+ 在这一点上我们目前使用的皇家版《莎士比亚全集》是做得最好的。
150
+ 那么我们该怎样来翻译莎士比亚的这种用语呢是迫于传统中国道德取向的习惯巧妙地回避还是尽可能忠实地传达莎士比亚的本真用意我们认为前此的译本依据各自所处时代的中国人道德价值的接受状态采用了相应的翻译对策出现了某种程度的曲译这是可以理解的是特定历史条件下的产物。但是历史在前进中国人的道德观已经有了很大的改变尤其是在性禁忌领域。说实话无论我们怎样真实地还原莎士比亚著作中的性双关描写比起当代文学作品中有时无所忌讳的淫秽描写来莎士比亚还真是有小巫见大巫的感觉。换句话说目前中国人在这方面的外来道德价值接受状态已经完全可以接受莎士比亚著作中的性双关用语了。因此我们的做法是尽可能真实还原莎士比亚性相关用语的现象。在通常的情况下如果直译不能实现这种现象的传输我们就采用注释。可以说在这方面目前这个版本是所有莎士比亚汉译本中做得最超前的。
151
+ 译法示例
152
+ 莎士比亚作品的文字具有多种风格早期的、中期的和晚期的语言风格有明显区别悲剧、喜剧、历史剧、十四行诗的语言风格也有区别。甚至同样是悲剧或喜剧莎士比亚的语言风格往往也会很不相同。比如同样是属于悲剧《罗密欧与朱丽叶》剧文中就常常有押韵的段落而大悲剧《李尔王》却很少押韵同样是喜剧《威尼斯商人》是格律素体诗而《温莎的风流娘儿们》却大多是散文体。
153
+ 与此现象相应我们的翻译当然也就有多种风格。虽然不完全一一对应但我们有意避免将莎士比亚著作翻译成千篇一律的一种文体。从这个意义上说皇家版《莎士比亚全集》汉译本在某些方面采用了全新的译法。这种全新译法不是孤立的一种译法而是力求展示多种翻译风格、多种审美尝试。多样化为我们将来精益求精提供了相对更多的选择。如果现在固定为一种单一的风格那么将来要想有新的突破就困难了。概括说来我们的多种翻译风格主要包括1有韵体诗词曲风味译法2有韵体现代文白融合译法3无韵体白话诗译法。下面依次选出若干相应风格的译例供读者和有关方面品鉴。
154
+ 一、有韵体诗词曲风味译法
155
+ 有韵体诗词曲风味译法注意使用一些传统诗词曲中诗味比较浓郁的词汇同时注意遣词不偏僻节奏比较明快音韵也比较和谐。但是它们并不是严格意义上的传统诗词曲只是带点诗词曲的风味而已。例如
156
+ 女巫甲 何时我等再相逢
157
+ 闪电雷鸣急雨中
158
+ 女巫乙 待到硝烟烽火静
159
+ 沙场成败见雌雄。
160
+ 女巫丙 残阳犹挂在西空。《麦克白》第一幕第一场
161
+ 小丑甲 当时年少爱风流
162
+ 有滋有味有甜头
163
+ 行乐哪管韶华逝
164
+ 天下柔情最销愁。《哈姆莱特》第五幕第一场
165
+ 朱丽叶 天未曙罗郎何苦别意匆忙
166
+ 鸟音啼声声亮惊骇罗郎心房。
167
+ 休听作破晓云雀歌只是夜莺唱
168
+ 石榴树间夜夜有它设歌场。
169
+ 信我罗郎端的只是夜莺轻唱。
170
+ 罗密欧 不是云雀报晓不是莺歌
171
+ 看东方无情朝阳暗洒霞光
172
+ 流云万朵镶嵌银带飘如浪。
173
+ 星斗如烛恰似残灯剩微芒
174
+ 欢乐白昼悄然驻步雾嶂群岗。
175
+ 奈何我去也则生留也必亡。
176
+ 朱丽叶 听我言天际微芒非破晓霞光
177
+ 只是金乌吐射流星当空亮
178
+ 似明炬今夜为郎朗照边邦
179
+ 何愁它曼托瓦路漫远悠长。
180
+ 且稍待正无须行色皇皇仓仓。
181
+ 罗密欧 纵身陷人手蒙斧钺加诛于刑场
182
+ 只要这勾留遂你愿我欣然承当。
183
+ 让我说那天际灰朦非黎明醒眼
184
+ 乃月神眉宇幽幽映现淡淡辉光
185
+ 那歌鸣亦非云雀之讴哪怕它
186
+ 嚣然振动于头上空冥嘹亮高亢。
187
+ 我巴不得栖身此地永不他往。
188
+ 来吧死亡倘朱丽叶愿遂此望。
189
+ 如何心肝畅谈吧趁夜色迷茫。《罗密欧与朱丽叶》第三幕第五场
190
+ 二、有韵体现代文白融合译法
191
+ 有韵体现代文白融合译法的特点是基本押韵措辞上白话与文言尽量能够水乳交融充分利用诗歌的现代节奏感俾便能够念起来朗朗上口。例如
192
+ 哈姆莱特 死还是生这才是问题根本
193
+ 莫道是苦海无涯但操戈奋进
194
+ 终赢得一片清平或默对逆运
195
+ 忍受它箭石交攻敢问
196
+ 两番选择何为上乘
197
+ 死灭睡也倘借得长眠
198
+ 可治心伤愈千万肉身苦痛痕
199
+ ���岂非美境人所追寻死睡也
200
+ 睡中或有梦魇生唉症结在此
201
+ 倘能撒手这碌碌凡尘长入死梦
202
+ 又谁知梦境何形念及此忧
203
+ 不由人踌躇难定这满腹疑情
204
+ 竟使人苟延年命忍对苦难平生。
205
+ 假如借短刀一柄即可解脱身心
206
+ 谁甘愿受人世的鞭挞与讥评
207
+ 强权者的威压傲慢者的骄横
208
+ 失恋的痛楚法律的耽延
209
+ 官吏的暴虐甚或默受小人
210
+ 对贤德者肆意拳脚加身
211
+ 谁又愿肩负这如许重担
212
+ 流汗、呻吟疲于奔命
213
+ 倘非对死后的处境心存疑云
214
+ 惧那未经发现的国土从古至今
215
+ 无孤旅归来意志的迷惘
216
+ 使我辈宁愿忍受现世的忧闷
217
+ 而不敢飞身投向未知的苦境
218
+ 前瞻后顾使我们全成懦夫
219
+ 于是本色天然的决断决行
220
+ 罩上了一层思想的惨淡余阴
221
+ 只可惜诸多待举的宏图大业
222
+ 竟因此如逝水忽然转向而行
223
+ 失掉行动的名分。《哈姆莱特》第三幕第一场
224
+ 麦克白 若做了便是了则快了便是好。
225
+ 若暗下毒手却能横超果报
226
+ 割人首级却赢得绝世功高
227
+ 则一击得手便大功告成
228
+ 千了百了那么此际此宵
229
+ 身处时间之海的沙滩、岸畔
230
+ 何管它来世风险逍遥。但这种事
231
+ 现世永远有裁判的公道
232
+ 教人杀戮之策者必受杀戮之报
233
+ 给别人下毒者自有公平正义之手
234
+ 让下毒者自食盘中毒肴。《麦克白》第一幕第七场
235
+ 损神耗精愧煞了浪子风流
236
+ 都只为纵欲眠花卧柳
237
+ 阴谋好杀赌假咒坏事做到头
238
+ 心毒手狠野蛮粗暴背信弃义不知羞。
239
+ 才尝得云雨乐转眼意趣休。
240
+ 舍命追求一到手没来由
241
+ 便厌腻个透。呀恰恰像是钓钩
242
+ 但吞香饵管教你六神无主不自由。
243
+ 求时疯狂得时也疯狂
244
+ 曾有现有还想有要玩总玩不够。
245
+ 适才是甜头转瞬成苦头。
246
+ 求欢同枕前梦破云雨后。
247
+ 唉普天下谁不知这般儿歹症候
248
+ 却避不得便往这通阴曹的天堂路儿上走十四行诗第一百二十九首
249
+ 三、无韵体白话诗译法
250
+ 无韵体白话诗译法的特点是虽然不押韵但是译文有很明显的和谐节奏措辞畅达有诗味明显不是普通的口语。例如
251
+ 贡妮芮 父亲我爱您非语言所能表达
252
+ 胜过自己的眼睛、天地、自由
253
+ 超乎世上的财富或珍宝犹如
254
+ 德貌双全、康强、荣誉的生命。
255
+ 子女献爱父亲见爱至多如此
256
+ 这种爱使言语贫乏谈吐空虚
257
+ 超过这一切的比拟——我爱您。《李尔王》第一幕第一场
258
+ 李尔 国王要跟康沃尔说话慈爱的父亲
259
+ 要跟他女儿说话命令、等候他们服侍。
260
+ 这话通禀他们了吗我的气血都飙起来了
261
+ 火爆火爆公爵去告诉那烈性公爵——
262
+ 不还是别急也许他是真不舒服。
263
+ 人病了常会疏忽健康时应尽的
264
+ 责任。身子受折磨
265
+ 逼着头脑跟它受苦
266
+ 人就不由自主了。我要忍耐
267
+ 不再顺着我过度的轻率任性
268
+ 把难受病人偶然的发作错认是
269
+ 健康人的行为。我的王权废掉算了
270
+ 为什么要他坐在这里这种行为
271
+ 使我相信公爵夫妇不来见我
272
+ 是伎俩。把我的仆人放出来。
273
+ 去跟公爵夫妇讲我要跟他们说话
274
+ 现在就要。叫他们出来听我说
275
+ 不然我要在他们房门前打起鼓来
276
+ 不让他们好睡。《李尔王》第二幕第二场
277
+ 奥瑟罗 诸位德高望重的大人
278
+ 我崇敬无比的主子
279
+ 我带走了这位元老的女儿
280
+ 这是真的真的我和她结了婚说到底
281
+ 这就是我最大的罪状再也没有什么罪名
282
+ 可以加到我头上了。我虽然
283
+ 说话粗鲁不会花言巧语
284
+ 但是七年来我用尽了双臂之力
285
+ 直到九个月前我一直
286
+ 都在战场上拼死拼活
287
+ 所以对于这个世界我只知道
288
+ 冲锋向前不敢退缩落后
289
+ 也不会用漂亮的字眼来掩饰
290
+ 不漂亮的行为。不过如果诸位愿意耐心听听
291
+ 我也可以把我没有化装掩盖的全部过程
292
+ 一五一十地摆到诸位面前接受批判
293
+ 我绝没有用过什么迷魂汤药、魔法妖术
294
+ 还有什么歪门邪道——反正我得到他的女儿
295
+ 全用不着这一套。《奥瑟罗》第一幕第三场
296
+ 注释
297
+ 1 见朱生豪大约在1936年夏致宋清如信“今天下午我试译了两页莎士比亚还算顺利不过恐怕终于不过是Poor Stuff而已。当然预备全部用散文译出否则将要了我的命。”《伉俪朱生豪宋清如诗文选》下卷中国青年出版社2013年第94页
298
+ 2 朱生豪“今天因为提起了精神却很兴奋晚上译了六千字今天一共译一万字。”同上第101页
299
+ 3 卞之琳《莎士比亚悲剧四种》方志出版社2007年第4页。
300
+ 《暴风雨》导言
301
+ 《暴风雨》几乎可以肯定是莎士比亚独立完成的最后一出戏。我们不知道他是否预期如此。这出戏也是印在第一对开本的第一个剧本。我们也不知道它得到如此尊贵的地位是因为对开本的编辑把它当作展示品——大师艺术的总和之作——还是为了更为平凡的理由他们手头有抄写员拉尔夫·克兰Ralph Crane的干净文本排版者要着手排版莎士比亚近乎百万字的浩大工程从这本起可以有个比较容易的开始。无论它的位置来自无心抑或刻意的安排自19世纪初期以来《暴风雨》成于莎士比亚写作生涯之终、又置于作品集之首的事实大大影响了后世对这出戏的反应。它已经被视为诠释莎士比亚的试金石。
302
+ 本剧内容集中于支配与统治的问题。在开场的暴风雨中正常的社会秩序大乱水手长命令廷臣因为知道咆哮的海浪根本不在乎“什么国王”。之后第一幕第二场中详细展开的背景故事揭露了不尊重公爵名号的阴谋家我们得知普洛斯彼罗失去了米兰的权力但补偿式地得以控制岛上的爱丽儿和凯列班。腓迪南和米兰达的同心结则指向米兰与那不勒斯未来的统治。还有更进一步的政治算计西巴斯辛与安东尼奥计划谋杀阿隆佐国王和忠厚大臣贡柴罗低贱出身的角色想要推翻普洛斯彼罗让酗酒的司膳官斯丹法诺当岛上的国王。普洛斯彼罗在爱丽儿和岛上其他精灵协助下演出了一幕幕精彩的戏——使谋反者动弹不得鸟身女妖与消失的盛筵众女神及农民的假面剧那对小情人对弈的情景——这些都有助于报复过去的罪愆恢复当前的秩序并预备和谐的来日。工作完毕之后爱丽儿获得释放心痛啊1而普洛斯彼罗也在精神上做好了死亡的准备。甚至凯列班都要“寻求恩典”。
303
+ 然而莎士比亚从来都不爱简单。普洛斯彼罗以戏法变出暴风雨把宫廷的达官贵人带到这座岛主要是为了强迫他那篡位的弟弟安东尼奥悔罪。可是到了两人面对面的高潮时刻对普洛斯彼罗的饶恕与要求安东尼奥却连一个字都没有回应。他完全没有以阿隆佐在前面几行的表现为榜样而仿效之。至于安东尼奥的共犯西巴斯辛竟然还胆敢说普洛斯彼罗魔法般的先见之明是仗着邪魔之力。普洛斯彼罗能力再大也无法预料或掌控人性。如果原本没有良心以后也无法创造出良心。
304
+ 塞缪尔·泰勒·柯尔律治Samuel Taylor Coleridge2把普洛斯彼罗描述为“简直就是风暴中的莎士比亚本人”。换句话说戏中主角在开场中变出暴风雨正如剧作家变出这部戏的整个世界。普洛斯彼罗的法术驾驭了自然力量好引领其他意大利角色加入他的放逐世界同样地莎士比亚的艺术先把舞台变成一艘大海中的船然后又变成“无人的荒岛”。“法术”乃是这出戏的关键词眼。凯列班是普洛斯彼罗的“他者”因为他代表自然状态。在达尔文主义盛行的19世纪他被重塑为人类与我们动物祖先之间过渡时期“缺失的那一环”。
305
+ 普洛斯彼罗的背景故事道出了从训练统治者的“人文素养”到比较危险的魔幻“法术”的变化过程。在莎士比亚时代魔法的思维普遍存在。人人从小都相信自然界之外另有一个世界就是灵魂与妖怪的世界。“自然”与“妖魔”乃是研究及操弄超自然现象的两大支派。魔法magic即是对隐秘事物的认知和制造奇迹的法术。某些人认为这是自然哲学的最高形式这个词源于magia在古波斯语里意思是“智慧”众人称之为“神秘哲学”。它假设有不同层级的力量从不具形体的“智性的”天使魂灵到天上恒星和行星的世界再到地球事物及其形体的变化。魔法师上达高阶力量的知识以人为方式将这些能力带下来制造出奇妙的效果。科尼利厄斯·阿格里帕Cornelius Agrippa3是《论神秘哲学》De occulta philosophia一书的作者主张必须有“仪式魔法”才能达到超越星球的天使智慧。这是最高也最危险的活动层次因为——诚如同克里斯托弗·马洛Christopher Marlowe4笔下的浮士德博士Dr. Faustus的发现——太容易变出魔鬼而不是天使。比较普通的“自然魔法”需要“媒合”天地与星体和物质世界元素之间的奇幻链接同工。历久不衰的星象影响观念乃是这种思维模式的残留。对文艺复兴时代的智者例如在米兰从业的吉罗拉莫·卡尔达诺Girolamo Cardano5而言医学、自然哲学、数学、星象学以及解梦都是紧密相连的。
306
+ 然而自然魔法始终无法躲开它的妖魔阴影。有一个像阿格里帕或卡尔达诺这样博学的智者就有一千个乡下“智婆”从事民俗医疗和算命。后者在前现代时期常常被妖魔化为女巫要为歉收、牲畜疾病及其他病痛负责。普洛斯彼罗强调他自己的白色魔法有别于凯列班母亲西考拉克斯的黑色魔法不过在这出戏里两者十分相似。他之所以从米兰被放逐到岛上是因为专注于自己的秘密研究从而给予了安东尼奥篡夺大公国的可乘之机而西考拉克斯之所以从阿尔及尔放逐到岛上是因为被控施行巫术他带着他的幼女来而西考拉克斯来的时候肚里怀着据说是跟魔鬼搞出来的孩子。两者都能指挥海潮操控以爱丽儿为代表的精灵世界。普洛斯彼罗��放弃他的魔法时用来描述法力的词语是借自另一个女巫——奥维德Ovid的古代神话故事巨著《变形记》Metamorphoses里的美狄亚Medea。在某个层次上普洛斯彼罗表达了他跟西考拉克斯之间的亲缘关系他说凯列班“这个妖怪嘛我/承认是我的”。此处主语和动词在行尾分开表明承认之前稍有犹豫这是莎士比亚后期灵活运用抑扬格五音步手法的极端例子。
307
+ 莎士比亚喜爱制造对立再把他的黑与白淡化成复杂道德里的灰色区块。在米兰普洛斯彼罗对人文素养的内观研究使他失去权位并促成暴政。在岛上他企图以他所学来弥补过失利用正向的魔法带来悔罪、收复大公国并且打造一个王朝的婚姻。然而在第五幕开始时他醒悟到真正的人性不在于运用智慧统治而在于实践更为严谨的基督徒式的德行。对16世纪的人文主义者来说君王的德行教育就是为了政治目的而修养智慧、宽宏、节制、正直。对普洛斯彼罗而言最终真正重要的是仁慈。而这是师父从徒弟那里学到的正是爱丽儿教了普洛斯彼罗“情感”的道理而不是相反。
308
+ 爱丽儿代表火与空气、和谐与音乐、耿耿忠心。凯列班属土关乎纷争、醉酒和反叛。爱丽儿的表达工具是雅致的诗凯列班的则大多是粗鲁乃至猥亵的散文一如弄臣特林鸠罗和醉汉司膳官斯丹法诺。然而令人讶异的是剧中最美丽的诗句乃是凯列班听到爱丽儿的音乐时所说的。即便是用散文凯列班亦与自然环境有一种美妙的协调他知道岛上每一个角落、每一种生物。普洛斯彼罗说他是“魔鬼天生的魔鬼对他的本性/教化根本是白搭”然而就在下一句台词里凯列班上场时说“拜托脚步轻些免得这只瞎眼的鼹鼠听到脚步声”如此富有想象力的语言立即否定了普洛斯彼罗的断言。
309
+ 凯列班据称曾要性侵米兰达可见普洛斯彼罗想驯服这个“怪物仆”、教育他具有人性的意图是失败的。然而这失败是谁的责任问题会不会出在普洛斯彼罗想要灌输到凯列班记忆里的内容上而非后者的天性一开始凯列班欢迎普洛斯彼罗到岛上来主动与他分享岛上水果——正如蒙田Montaigne散文《论食人部族》“Of the Cannibals”里所写的“高贵的野蛮人”那样那篇文章是莎士比亚剧中引用的另一来源贡柴罗治理本岛的乌托邦式“黄金时代”理想便是采自蒙田作品的英译本。凯列班只不过表现出普洛斯彼罗印刻在他身上的那种低贱而已使凯列班“污秽”的可能是普洛斯彼罗说他是“秽物”的教导。
310
+ 凯列班了解书的重要性正如现代政变领导者首先要占据电视台他强调反叛普洛斯彼罗必须从夺取他的书籍开始。然而斯丹法诺另有其书。他对凯列班说“这东西能叫您说话”—他复制普洛斯彼罗通过语言取得控制的手法不过是以另一种模式。文本的灌输被美酒的熏陶取代所亲吻的书乃是酒瓶。如此一来莎士比亚的场景对位技法营造出对话精神质疑了普洛斯彼罗的书籍使用。若说斯丹法诺和特林鸠罗以酒精达成普洛斯彼罗以教导所达成的目的两者都说服凯列班服役并分享岛上的果实这岂不是显出教导有可能只是社会控制的工具而已普洛斯彼罗时常似对他以教学建立的权力结构较感兴趣胜过他教导的实质内容。很难看出逼腓迪南搬运木柴是为了教诲德行目的其实是要他臣服。
311
+ 来到一个没有欧洲人居住的岛屿谈论“殖民地”与一个“野人”相遇并用酒精交换生存技能在语言学习过程中确立谁是主、谁是奴担心奴仆会使主人的女儿受孕欲使野蛮人寻求基督教的“恩典”但又提议把他运到英格兰展示获利提到百慕大危险的气候以及一个“华丽新世界”在所有这些方面《暴风雨》都唤起了欧洲的殖民主义精神。莎士比亚与弗吉尼亚公司的成员有联系。该公司奉王室之命成立于1606年为次年在美洲建立詹姆斯敦殖民地起了重要作用。1610年秋有一封信寄达英格兰描述派往增援殖民地的舰队在加勒比海被暴风雨吹散搭载新总督的那艘船被吹到百慕大船员和乘客都在那里过冬。虽然那封信当时没有出版手稿却流传开来至少引发两本小册子讨论这些事件。学者们为莎士比亚究竟直接引用了其中多少材料而争论不休但暴风雨及岛屿的某些细节好像是从中取材。毋庸置疑的是总督及其团队看似奇迹般幸存同时他们在巴哈马群岛发现的富饶环境乃是本剧写作之时的公众流行话题。
312
+ 大英帝国、奴隶贩卖、东西海路运送香料带来的财富——这些是后来的事。莎士比亚的戏设定在地中海不在加勒比海。凯列班严格说来不能算是岛上的原住民。然而这出戏直觉地感知殖民时期占有与驱离的动能剧力��钧不可思议所以1950年奥克塔夫·曼诺尼Octave Mannoni6写的《殖民地化进程中的心理学》The Psychology of Colonisation主张说殖民过程的运作要经由一对精神官能症交互作用于殖民者是“普洛斯彼罗情结”于被殖民者是“凯列班情结”。就是为了回应曼诺尼弗朗茨·法农Frantz Fanon7写了《黑皮肤白面具》Black Skin, White Masks从而在很大程度上塑造了“后殖民”时代的知识领域。对20世纪后期许多以英文写作的加勒比海作家来说《暴风雨》这出戏尤其是凯列班这个人物成为他们发现自己文学声音的焦点。这出戏与其说是对帝国历史的反思毋宁说是对这段历史的预知——毕竟普洛斯彼罗是被流放的人不是冒险家。
313
+ 国王剧团经常奉命在白厅御前献演自然知道从1608年岁暮起十几岁的伊丽莎白公主Princess Elizabeth就住在王宫里。她是有文化素养的少女喜欢音乐和舞蹈参与宫中节庆活动1610年在一出名叫《忒堤斯》Tethys8的假面剧里担任舞者。假面剧由皇亲、廷臣、职业演员混搭演出场面壮观音乐精致在那些年日是宫廷最时兴的表演。与莎士比亚亦友亦敌的本·琼森Ben Jonson9和设计师伊尼戈·琼斯Inigo Jones10合作为自己打出当代首席假面剧作家的名号。1608年他引进“反假面剧”或称“前假面剧”让丑怪人物即所谓“怪胎”在优雅、和谐的假面剧演出之前狂舞一番。莎士比亚也采纳了当时的流行风尚在《暴风雨》的戏中加入了订婚的假面剧以及凯列班、斯丹法诺和特林鸠罗三人闻马尿、偷窃晾衣绳上的衣服、遭群狗追逐的反假面闹剧。我们甚至觉得普洛斯彼罗这个人物可能就是对本·琼森温和的诙谐模拟他的戏剧想象受制于古典式对时间与场景统一性的要求一如琼森他也演出宫廷假面剧一如琼森。或许正因为如此几年之后琼森在他的《巴托罗缪市集》Bartholomew Fair里戏仿《暴风雨》作为回敬。
314
+ 普洛斯彼罗的基督教语言在收场白中持续最久然而他最后请求宽容的对象不是上帝而是观众。到了最后一刻取代人文主义学术的不是基督教信仰而是戏剧的信念。因此这出戏可以解读为莎士比亚为自己戏剧艺术的辩护——从浪漫主义时期以来常常就是如此理解。不过反讽的是这出戏本身对书籍乃至于对剧场的功能十分怀疑。魔法书沉入大海而假面剧及其演员也溶入空气之中就像“无根的幻景”或一场梦。
315
+ 参考资料
316
+ 剧情十二年前在那不勒斯国王阿隆佐及其弟西巴斯辛协助下米兰公爵普洛斯彼罗被他的弟弟安东尼奥篡了位。普洛斯彼罗及其幼女米兰达被流放大海到达远方小岛。他在那里靠着魔法统治精灵爱丽儿和野人凯列班。他利用法力呼风唤雨使他的敌人遭遇船难来到岛上。阿隆佐寻找儿子腓迪南担心他已经淹死。西巴斯辛密谋杀害阿隆佐夺取他的王位。酗酒的司膳官斯丹法诺和弄臣特林鸠罗遇见凯列班听了他的劝说要杀害普洛斯彼罗好由他们来统治这座岛。腓迪南和米兰达相遇两人一见钟情。普洛斯彼罗要考验腓迪南命其做苦工腓迪南通过考验普洛斯彼罗为这对年轻情侣演了一出贺婚的假面剧。在普洛斯彼罗的计划接近高潮时他正面质问敌人并宽恕他们。普洛斯彼罗赐予爱丽儿自由准备离开岛屿返回米兰。
317
+ 主要角色列有台词行数百分比/台词段数/上场次数普洛斯彼罗30/115/5爱丽儿9/45/6凯列班8/50/5斯丹法诺7/60/4贡柴罗7/52/4西巴斯辛5/67/4安东尼奥6/57/4米兰达6/49/4腓迪南6/31/4阿隆佐5/40/4特林鸠罗4/39/4。
318
+ 语体风格诗体约占80散体约占20。
319
+ 创作年代1611年。1611年11月1日宫廷演出使用的部分素材于1610年秋季以前并未问世。
320
+ 取材来源主要剧情不知取自何处但暴风雨和岛屿的某些细节似乎来自威廉·斯特雷奇William Strachey所著《托马斯·盖茨爵士船难获救真实报导》A True Reportory of the Wreck and Redemption of Sir Thomas Gates, Knight写于1610年收入1625年出版的《珀切斯游记》[Purchas his Pilgrims]或许还有西尔韦斯特·乔丹Sylvester Jourdain的《百慕大发现记》A Discovery of the Bermudas, 1610年以及弗吉尼亚公司发行的小册子《弗吉尼亚殖民地资产真实报告》A True Declaration of the Estate of the Colony in Virginia1610年有几处提到维吉尔Virgil11的《埃涅阿斯纪》Aeneid与奥维德的《变形记》特别是在第五幕第一场模仿阿瑟·戈尔丁Arthur Golding1567年翻译奥维德第七卷内美狄亚的咒文贡柴罗在第二幕第一场关于“黄金时代”的说辞基于约翰·弗洛里奥John Florio1603年所译蒙田《论食人部族》一文两者十分接近。
321
+ 文本1623年的第一对开本是唯一早期印刷本。所据为国王剧团所雇专业誊录员拉尔夫·克兰的抄写本。总体说来��高质量的印刷本。
322
+ 乔纳森·贝特Jonathan Bate
323
+ 注释
324
+ 1 或因普洛斯彼罗舍不得爱丽儿。——译者附注
325
+ 2 柯尔律治1772—1834英国诗人、评论家。——译者附注
326
+ 3 阿格里帕1486—1535德国医生、神学家、神秘学家。——译者附注
327
+ 4 马洛1564—1593英国伊丽莎白时期剧作家、诗人。——译者附注
328
+ 5 卡尔达诺1501—1576意大利医生、数学家、占星术家。——译者附注
329
+ 6 曼诺尼1899—1989法国精神分析学家、作家。——译者附注
330
+ 7 法农1925—1961出生于法属加勒比海岛屿马提尼克岛精神分析学家、哲学家。——译者附注
331
+ 8 忒堤斯为古希腊神话中的女海神之名。——译者附注
332
+ 9 琼森1572—1637英国剧作家、诗人、评论家。——译者附注
333
+ 10 琼斯1573—1652英国画家、建筑师、设计师。——译者附注
334
+ 11 维吉尔前70—前19奥古斯都时代的古罗马诗人。——译者附注
335
+ 暴风雨
336
+ 普洛斯彼罗合法的米兰公爵
337
+ 米兰达普洛斯彼罗之女
338
+ 阿隆佐那不勒斯国王
339
+ 西巴斯辛阿隆佐之弟
340
+ 安东尼奥普洛斯彼罗之弟篡位的米兰公爵
341
+ 腓迪南那不勒斯国王之子
342
+ 贡柴罗忠诚的老枢密大臣
343
+ 阿德里安和弗兰西斯科两贵族
344
+ 特林鸠罗弄臣
345
+ 斯丹法诺酗酒的司膳官
346
+ 船长
347
+ 水手长
348
+ 众水手
349
+ 凯列班未驯化的畸形奴隶
350
+ 爱丽儿空气精灵
351
+ 场景无人的荒岛
352
+ 第一幕1
353
+ 第一场第一景
354
+ 海中一船
355
+ 雷电交加暴风雨声可闻。船长与水手长上
356
+ 船长 水手长
357
+ 水手长 在船长。有什么吩咐
358
+ 船长 好兄弟去跟水手们说动作要快不然咱会搁浅啦快赶快
359
+
360
+ 众水手上
361
+ 水手长 嘿哥儿们加油加油哥儿们快点快点把中桅帆收一收。听船长的哨音。——尽管刮吧刮到你喘不过气也没关系只要船掉得过头来。
362
+ 对风暴
363
+ 阿隆佐、西巴斯辛、安东尼奥、腓迪南、贡柴罗及其他人上
364
+ 阿隆佐 好水手长留意点儿。船长在哪儿拿出男子气概来。
365
+ 水手长 各位请待在下头。
366
+ 安东尼奥 船长在哪儿啊水手长
367
+ 水手长 您没听见他吗您碍着我们的事啦。待在舱里你们这是在帮助暴风雨。
368
+ 贡柴罗 别那么说好兄弟耐心点。
369
+ 水手长 先得等大海有耐心。走开这些个大吼大叫的会理你什么国王吗去舱里闭嘴别烦我们。
370
+ 贡柴罗 好兄弟可要记得你船上载的是谁。
371
+ 水手长 没一个是我爱得超过我自个儿的。您是个大臣要是您能命令这些风雨不作声现在就平静那咱们就一根绳索都不管。施展您的权威吧。要是您办不到就感谢您活了这把年纪回舱里预备随时有什么不测——万一真有的话。——加油兄弟们——
372
+ 对众水手
373
+ 别挡了我们我说。
374
+ 对众大臣
375
+ [阿隆佐、西巴斯辛、安东尼奥与腓迪南随水手长及众水手]下
376
+ 贡泽罗 这家伙让我非常安慰。我看他没有淹死的凶相他那张脸分明就该是被绞死的。2善良的命运之神哪千万要让他被绞死用他命中注定的绞绳作我们的定锚缆索吧因为我们自己的不管用了。他若不是注定该被绞死的我们的处境就悲惨啰。
377
+
378
+ 水手长上
379
+ 水手长 放低中桅快再低再低尽量把船固定住。幕内一声呼喊混蛋叫成这样他们比这天气、比咱们发号施令还大声。
380
+ 西巴斯辛、安东尼奥与贡柴罗上
381
+ 又来啦你们来干吗的想叫我们放弃、淹死你们想要沉船哪
382
+ 西巴斯辛 我咒你喉咙长脓包你这个大吼大叫、亵渎神明、没有慈悲心肠的狗
383
+ 水手长 那你们来干。
384
+ 安东尼奥 绞死你狗东西绞死你婊子养的无耻大嗓门我们才没有你那么怕被淹死呢。
385
+ 贡柴罗 我敢担保他不会淹死就算这条船比个坚果的壳儿还小而且比流个不停的3女人漏得还凶。
386
+ 水手长 顶住风顶住风两张帆都升起来再出海升起来
387
+ 众水手浑身湿透上
388
+ 众水手 完蛋了快祷告祷告完蛋了
389
+ 水手长 什么我们都得淹死
390
+ 贡柴罗 王上和王子在祷告。咱们去助祷我们情况一样。
391
+ 西巴斯辛 我没耐性了。
392
+ 安东尼奥 我们根本是被酒鬼害了命。这个大嘴巴的无赖你淹死算了还让潮水冲刷十遍
393
+ 贡柴罗 他还是会被绞死的
394
+ 尽管每一滴海水都赌誓不会
395
+ 而且张着大口要吞他。
396
+ 水手长及众水手下
397
+ 幕内喧闹声
398
+ [后台人声] 可怜我们吧——船裂了船裂了——别了我的妻儿——别了兄弟——船裂了船裂了船裂了
399
+ 安东尼奥 咱们跟王上一起沉了吧。
400
+ 西巴斯辛 咱们去向他道别。
401
+ [安东尼奥与西巴斯辛]下
402
+ 贡柴罗 这时我情愿用千顷波涛去换一亩荒地长长的灌木、棕色的荆豆什么都行。愿上天的旨意成就但我情愿死在旱地。
403
+
404
+ 第二场第二景
405
+ 本剧以下场景都在普洛斯彼罗的海岛的各处
406
+ 普洛斯彼罗4与米兰达5上
407
+ 米兰达 至爱的父亲您若是借了法术
408
+ 使这狂涛咆哮请平息它们。
409
+ 上天好像要倾倒恶臭的沥青
410
+ 亏得大海上升到苍��的脸颊
411
+ 熄灭了天火6。看到他们受苦我
412
+ 一同受苦。美轮美奂的一艘船——
413
+ 上面想必载着高贵的人物——
414
+ 都撞成了碎片。啊那喊叫声打在
415
+ 我的心坎上。那些可怜人都完了。
416
+ 假如我是个有权能的神我会
417
+ 先把大海沉入地下不让它
418
+ 如此吞灭这艘美好的船还有
419
+ 船里的人。
420
+ 普洛斯彼罗 安心吧
421
+ 不必再害怕。告诉你怜悯的心肠
422
+ 并没有造成损伤。
423
+ 米兰达 啊可怜哪
424
+ 普洛斯彼罗 没事。
425
+ 我所做的没有不是为了你——
426
+ 为了你我亲爱的你我女儿——你
427
+ 不明白你的身份根本不知道
428
+ 我的来历也不知道我的高贵
429
+ 超过普洛斯彼罗一个破洞窟的主人
430
+ 不过尔尔的你的父亲。
431
+ 米兰达 我从来没有
432
+ 想过要知道得更详细。
433
+ 普洛斯彼罗 时候已到
434
+ 我该多告诉你一些。帮我
435
+ 脱下我这件魔法斗篷。这样
436
+ 放下魔法斗篷
437
+ 躺好了我的魔法。你擦擦眼睛放心。
438
+ 那船难的恐怖景象触动了
439
+ 你内心至情至性的哀矜
440
+ 但我在我法术之中早已预作
441
+ 安排不叫船上任何人——
442
+ 对甚至任何生物——有
443
+ 一根毛发受到损伤尽管你
444
+ 听到哀嚎看见船沉。坐下吧
445
+ 米兰达坐下
446
+ 因为现在你必须多了解一些。
447
+ 米兰达 您常常
448
+ 要跟我讲我的身份却欲言又止
449
+ 我想追问终是徒然因您
450
+ 最后总说“慢着时机未到。”
451
+ 普洛斯彼罗 现在时机已到
452
+ 就在此刻你要张开耳朵
453
+ 听话要专心。你可记得
454
+ 我们来到这洞窟之前的时候
455
+ 我想你不能因为你那时还
456
+ 不满三岁。
457
+ 米兰达 我当然能够大人。
458
+ 普洛斯彼罗 记得什么呢有别的房屋或人吗
459
+ 告诉我有什么东西的形象
460
+ 还保存在你的记忆里。
461
+ 米兰达 很久远了
462
+ 我记得的比较像是一场梦
463
+ 不能保证准确无误。我不是
464
+ 曾经有四五个女人照顾吗
465
+ 普洛斯彼罗 你有还更多呢米兰达。可是这
466
+ 怎么还会留在你心中在时间黑暗的
467
+ 过去和深渊中你还看到什么
468
+ 你既然记得来此以前的事
469
+ 或许也记得你是怎么来的。
470
+ 米兰达 那我倒记不得了。
471
+ 普洛斯彼罗 十二年了米兰达十二年了
472
+ 你父亲原是米兰公爵一个
473
+ 大权在握的亲王。
474
+ 米兰达 大人您不是我父亲
475
+ 普洛斯彼罗 你母亲是美德的典范而
476
+ 她说你是我的女儿你父亲
477
+ 是米兰公爵他唯一的继承人
478
+ 公主也同样出身高贵。
479
+ 米兰达 啊天哪
480
+ 是什么卑鄙算计害我们流落至此
481
+ 还是说该算幸运呢
482
+ 普洛斯彼罗 都是都是孩子。
483
+ 就如你说的我们被卑鄙算计抛弃
484
+ 但幸运地获救于此。
485
+ 米兰达 啊我的心会淌血
486
+ 要是想到我给您添的麻烦
487
+ 但现在都不记得了。您请说下去。
488
+ 普洛斯彼罗 我弟弟就是你叔父叫安东尼奥的——
489
+ 我请你听好了——做兄弟的竟然
490
+ 会这样背信——世界上除了你以外
491
+ 他是我的最爱还托付他
492
+ 管理我邦的政务那时候啊
493
+ 所有城邦中要数米兰第一
494
+ 而普洛斯彼罗是至尊公爵享有如此
495
+ 殊荣说到人文素养7
496
+ 无人能比。我既一心一意钻研
497
+ 便把政务交给弟弟
498
+ 对我邦大事愈发生疏因为全神
499
+ 贯注于玄秘研究。你那虚伪的叔父——
500
+ 你在听吗
data/test_en.txt ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Wuthering Heights
2
+
3
+
4
+ --------------------------------------------------------------------------------
5
+
6
+ Chapter 2
7
+
8
+ Chinese
9
+
10
+
11
+ Yesterday afternoon set in misty and cold. I had half a mind to spend it by my study fire, instead of wading through heath and mud to Wuthering Heights. On coming up from dinner, however (N.B. I dine between twelve and one o'clock; the housekeeper, a matronly lady, taken as a fixture along with the house, could not, or would not, comprehend my request that I might be served at five), on mounting the stairs with this lazy intention, and stepping into the room, I saw a servant girl on her knees surrounded by brushes and coal-scuttles, and raising an infernal dust as she extinguished the flames with heaps of cinders. This spectacle drove me back immediately; I took my hat, and, after a four-miles' walk, arrived at Heathcliff's garden gate just in time to escape the first feathery flakes of a snow shower.
12
+
13
+ On that bleak hill top the earth was hard with a black frost, and the air made me shiver through every limb. Being unable to remove the chain, I jumped over, and, running up the flagged causeway bordered with straggling gooseberry bushes, knocked vainly for admittance, till my knuckles tingled and the dogs howled.
14
+
15
+ `Wretched inmates!' I ejaculated mentally, `you deserve perpetual isolation from your species for your churlish inhospitality. At least, I would not keep my doors barred in the day time. I don't care--I will get in!' So resolved, I grasped the latch and shook it vehemently. Vinegar-faced Joseph projected his head from a round window of the barn.
16
+
17
+ `Whet are ye for?' he shouted. `T' maister's dahn i' t' fowld. Go rahnd by th' end ut' laith, if yah went tuh spake tull him.'
18
+
19
+ `Is there nobody inside to open the door?' I hallooed, responsively.
20
+
21
+ `They's nobbut t' missis; and shoo'll nut oppen't an ye mak yer flaysome dins till neeght.'
22
+
23
+ `Why? Cannot you tell her who I am, eh, Joseph?'
24
+
25
+ `Nor-ne me! Aw'll hae noa hend wi't,' muttered the head, vanishing.
26
+
27
+ The snow began to drive thickly. I seized the handle to essay another trial; when a young man without coat, and shouldering a pitchfork, appeared in the yard behind. He hailed me to follow him, and, after marching through a wash-house, and a paved area containing a coal shed, pump, and pigeon cot, we at length arrived in the huge, warm, cheerful apartment, where I was formerly received. It glowed delightfully in the radiance of an immense fire, compounded of coal, peat, and wood; and near the table, laid for a plentiful evening meal, I was pleased to observe the `missis', an individual whose existence I had never previously suspected. I bowed and waited, thinking she would bid me take a seat. She looked at me, leaning back in her chair, and remained motionless and mute.
28
+
29
+ `Rough weather!' I remarked. `I'm afraid, Mrs Heathcliff, the door must bear the consequence of your servants' leisure attendance: I had hard work to make them hear me.'
30
+
31
+ She never opened her mouth. I stared--she stared also: at any rate, she kept her eyes on me in a cool, regardless manner, exceedingly embarrassing and disagreeable.
32
+
33
+ `Sit down,' said the young man gruffly. `He'll be in soon.'
34
+
35
+ I obeyed; and hemmed, and called the villain Juno, who deigned, at this second interview, to move the extreme tip of her tail, in token of owning my acquaintance.
36
+
37
+ `A beautiful animal!' I commenced again. `Do you intend parting with the little ones, madam?'
38
+
39
+ `They are not mine,' said the amiable hostess, more repellingly than Heathcliff himself could have replied.
40
+
41
+ `Ah, your favourites are among these?' I continued, turning to an obscure cushion full of something like cats.
42
+
43
+ `A strange choice of favourites!' she observed scornfully.
44
+
45
+ Unluckily, it was a heap of dead rabbits. I hemmed once more, and drew closer to the hearth, repeating my comment on the wildness of the evening.
46
+
47
+ `You should not have come out,' she said, rising and reaching from the chimney-piece two of the painted canisters.
48
+
49
+ Her position before was sheltered from the light; now, I had a distinct view of her whole figure and countenance. She was slender, and apparently scarcely past girlhood: an admirable form, and the most exquisite little face that I have ever had the pleasure of beholding; small features, very fair; flaxen ringlets, or rather golden, hanging loose on her delicate neck; and eyes, had they been agreeable in expression, they would have been irresistible: fortunately for my susceptible heart, the only sentiment they evinced hovered between scorn, and a kind of desperation, singularly unnatural to be detected there. The canisters were almost out of her reach; I made a motion to aid her; she turned upon me as a miser might turn if anyone attempted to assist him in counting his gold.
50
+
51
+ `I don't want your help,' she snapped; `I can get them for myself.'
52
+
53
+ `I beg your pardon!' I hastened to reply.
54
+
55
+ `Were you asked to tea?' she demanded, tying an apron over her neat black frock, and standing with a spoonful of the leaf poised over the pot.
56
+
57
+ `I shall be glad to have a cup,' I answered.
58
+
59
+ `Were you asked?' she repeated.
60
+
61
+ `No,' I said, half smiling. `You are the proper person to ask me.'
62
+  
63
+
64
+
65
+ Contents PreviousChapter
66
+ NextChapter
67
+
68
+
69
+ Homepage
data/test_zh.txt ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 呼啸山庄
2
+
3
+ --------------------------------------------------------------------------------
4
+
5
+ 第二章
6
+
7
+ 英文
8
+
9
+
10
+ 昨天下午又冷又有雾。我想就在书房炉边消磨一下午,不想踩着杂草污泥到呼啸山庄了。
11
+
12
+ 但是,吃过午饭(注意——我在十二点与一点钟之间吃午饭,而可以当作这所房子的附属物的管家婆,一位慈祥的太太却不能,或者并不愿理解我请求在五点钟开饭的用意),在我怀着这个懒惰的想法上了楼,迈进屋子的时候,看见一个女仆跪在地上,身边是扫帚和煤斗。她正在用一堆堆煤渣封火,搞起一片弥漫的灰尘。这景象立刻把我赶回头了。我拿了帽子,走了四里路,到达了希刺克厉夫的花园口口,刚好躲过了一场今年初降的鹅毛大雪。
13
+
14
+ 在那荒凉的山顶上,土地由于结了一层黑冰而冻得坚硬,冷空气使我四肢发抖。我弄不开门链,就跳进去,顺着两边种着蔓延的醋栗树丛的石路跑去。我白白地敲了半天门,一直敲到我的手指骨都痛了,狗也狂吠起来。
15
+
16
+ “倒霉的人家!”我心里直叫,“只为你这样无礼待客,就该一辈子跟人群隔离。我至少还不会在白天把门闩住。我才不管呢——我要进去!”如此决定了。我就抓住门闩,使劲摇它。苦脸的约瑟夫从谷仓的一个圆窗里探出头来。
17
+
18
+ “你干吗?”他大叫。“主人在牛栏里,你要是找他说话,就从这条路口绕过去。”
19
+
20
+ “屋里没人开门吗?”我也叫起来。
21
+
22
+ “除了太太没有别人。你就是闹腾到夜里,她也不会开。”
23
+
24
+ “为什么?你就不能告诉她我是谁吗,呃,约瑟夫?”
25
+
26
+ “别找我!我才不管这些闲事呢,”这个脑袋咕噜着,又不见了。
27
+
28
+ 雪开始下大了。我握住门柄又试一回。这时一个没穿外衣的年轻人,扛着一根草耙,在后面院子里出现了。他招呼我跟着他走,穿过了一个洗衣房和一片铺平的地,那儿有煤棚、抽水机和鸽笼,我们终于到了我上次被接待过的那间温暖的、热闹的大屋子。煤、炭和木材混合在一起燃起的熊熊炉火,使这屋子放着光彩。在准备摆上丰盛晚餐的桌旁,我很高兴地看到了那位“太太”,以前我从未料想到会有这么一个人存在的。我鞠躬等候,以为她会叫我坐下。她望望我,往她的椅背一靠,不动,也不出声。
29
+
30
+ “天气真坏!”我说,“希刺克厉夫太太,恐怕大门因为您的仆人偷懒而大吃苦头,我费了好大劲才使他们听见我敲门!”
31
+
32
+ 她死不开口。我瞪眼——她也瞪眼。反正她总是以一种冷冷的、漠不关心的神气盯住我,使人十分窘,而且不愉快。
33
+
34
+ “坐下吧,”那年轻人粗声粗气地说,“他就要来了。”
35
+
36
+ 我服从了;轻轻咳了一下,叫唤那恶狗朱诺。临到第二次会面,它总算赏脸,摇起尾巴尖,表示认我是熟人了。
37
+
38
+ “好漂亮的狗!”我又开始说话。“您是不是打算不要这些小的呢,夫人?”
39
+
40
+ “那些不是我的,”这可爱可亲的女主人说,比希刺克厉夫本人所能回答的腔调还要更冷淡些。
41
+
42
+ “啊,您所心爱的是在这一堆里啦!”我转身指着一个看不清楚的靠垫上那一堆像猫似的东西,接着说下去。
43
+
44
+ “谁会爱这些东西那才怪呢!”她轻蔑地说。
45
+
46
+ 倒霉,原来那是堆死兔子。我又轻咳一声,向火炉凑近些,又把今晚天气不好的话评论一通。
47
+
48
+ “你本来就不该出来。”她说,站起来去拿壁炉台上的两个彩色茶叶罐。
49
+
50
+ 她原先坐在光线被遮住的地方,现在我把她的全身和面貌都看得清清楚楚。她苗条,显然还没有过青春期。挺好看的体态,还有一张我生平从未有幸见过的绝妙的小脸蛋。五官纤丽,非常漂亮。淡黄色的卷发,或者不如说是金黄色的,松松地垂在她那细嫩的颈上。至于眼睛,要是眼神能显得和悦些,就要使人无法抗拒了。对我这容易动情的心说来倒是常事,因为它们所表现的只是在轻蔑与近似绝望之间的一种情绪,而在那张脸上看见那样的眼神是特别不自然的。
51
+
52
+ 她简直够不到茶叶罐。我动了一动,想帮她一下。她猛地扭转身向我,像守财奴看见别人打算帮他数他的金子一样。
53
+
54
+ “我不要你帮忙,”她怒气冲冲地说,“我自己拿得到。”
55
+
56
+ “对不起!”我连忙回答。
57
+
58
+ “是请你来吃茶的吗?”她问,把一条围裙系在她那干净的黑衣服上,就这样站着,拿一匙茶叶正要往茶壶里倒。
59
+
60
+ “我很想喝杯茶。”我回答。
61
+
62
+ “是请你来的吗?”她又问。
63
+
64
+ “没有,”我说,勉强笑一笑。“您正好请我喝茶。”
65
+
66
+  
67
+
68
+
69
+ 目录
70
+ 上一章
71
+ 下一章
72
+
73
+
74
+ 返回首页
data/text1.lzma ADDED
Binary file (29 kB). View file
data/text2.lzma ADDED
Binary file (16.5 kB). View file
gradio_queue.db ADDED
Binary file (16.4 kB). View file
nodemon.json ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "restartable": "rs",
3
+ "ignore": [
4
+ ".venv",
5
+ ".git",
6
+ "node_modules/**/node_modules",
7
+ "**/__pycache__"
8
+ ],
9
+ "verbose": true,
10
+ "execMap": {
11
+ "js": "node --harmony"
12
+ },
13
+ "watch": [
14
+ "tests",
15
+ "test/fixtures/",
16
+ "test/samples/"
17
+ ],
18
+ "env": {
19
+ "NODE_ENV": "development"
20
+ },
21
+ "ext": "js json py"
22
+ }
poetry.lock ADDED
@@ -0,0 +1,1080 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [[package]]
2
+ name = "analytics-python"
3
+ version = "1.4.0"
4
+ description = "The hassle-free way to integrate analytics into any python application."
5
+ category = "main"
6
+ optional = false
7
+ python-versions = "*"
8
+
9
+ [package.dependencies]
10
+ backoff = "1.10.0"
11
+ monotonic = ">=1.5"
12
+ python-dateutil = ">2.1"
13
+ requests = ">=2.7,<3.0"
14
+ six = ">=1.5"
15
+
16
+ [package.extras]
17
+ test = ["mock (==2.0.0)", "pylint (==1.9.3)", "flake8 (==3.7.9)"]
18
+
19
+ [[package]]
20
+ name = "backoff"
21
+ version = "1.10.0"
22
+ description = "Function decoration for backoff and retry"
23
+ category = "main"
24
+ optional = false
25
+ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
26
+
27
+ [[package]]
28
+ name = "bcrypt"
29
+ version = "3.2.0"
30
+ description = "Modern password hashing for your software and your servers"
31
+ category = "main"
32
+ optional = false
33
+ python-versions = ">=3.6"
34
+
35
+ [package.dependencies]
36
+ cffi = ">=1.1"
37
+ six = ">=1.4.1"
38
+
39
+ [package.extras]
40
+ tests = ["pytest (>=3.2.1,!=3.3.0)"]
41
+ typecheck = ["mypy"]
42
+
43
+ [[package]]
44
+ name = "certifi"
45
+ version = "2021.10.8"
46
+ description = "Python package for providing Mozilla's CA Bundle."
47
+ category = "main"
48
+ optional = false
49
+ python-versions = "*"
50
+
51
+ [[package]]
52
+ name = "cffi"
53
+ version = "1.15.0"
54
+ description = "Foreign Function Interface for Python calling C code."
55
+ category = "main"
56
+ optional = false
57
+ python-versions = "*"
58
+
59
+ [package.dependencies]
60
+ pycparser = "*"
61
+
62
+ [[package]]
63
+ name = "charset-normalizer"
64
+ version = "2.0.9"
65
+ description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
66
+ category = "main"
67
+ optional = false
68
+ python-versions = ">=3.5.0"
69
+
70
+ [package.extras]
71
+ unicode_backport = ["unicodedata2"]
72
+
73
+ [[package]]
74
+ name = "click"
75
+ version = "8.0.3"
76
+ description = "Composable command line interface toolkit"
77
+ category = "main"
78
+ optional = false
79
+ python-versions = ">=3.6"
80
+
81
+ [package.dependencies]
82
+ colorama = {version = "*", markers = "platform_system == \"Windows\""}
83
+ importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
84
+
85
+ [[package]]
86
+ name = "colorama"
87
+ version = "0.4.4"
88
+ description = "Cross-platform colored terminal text."
89
+ category = "main"
90
+ optional = false
91
+ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
92
+
93
+ [[package]]
94
+ name = "cryptography"
95
+ version = "36.0.1"
96
+ description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
97
+ category = "main"
98
+ optional = false
99
+ python-versions = ">=3.6"
100
+
101
+ [package.dependencies]
102
+ cffi = ">=1.12"
103
+
104
+ [package.extras]
105
+ docs = ["sphinx (>=1.6.5,!=1.8.0,!=3.1.0,!=3.1.1)", "sphinx-rtd-theme"]
106
+ docstest = ["pyenchant (>=1.6.11)", "twine (>=1.12.0)", "sphinxcontrib-spelling (>=4.0.1)"]
107
+ pep8test = ["black", "flake8", "flake8-import-order", "pep8-naming"]
108
+ sdist = ["setuptools_rust (>=0.11.4)"]
109
+ ssh = ["bcrypt (>=3.1.5)"]
110
+ test = ["pytest (>=6.2.0)", "pytest-cov", "pytest-subtests", "pytest-xdist", "pretend", "iso8601", "pytz", "hypothesis (>=1.11.4,!=3.79.2)"]
111
+
112
+ [[package]]
113
+ name = "cycler"
114
+ version = "0.11.0"
115
+ description = "Composable style cycles"
116
+ category = "main"
117
+ optional = false
118
+ python-versions = ">=3.6"
119
+
120
+ [[package]]
121
+ name = "ffmpy"
122
+ version = "0.3.0"
123
+ description = "A simple Python wrapper for ffmpeg"
124
+ category = "main"
125
+ optional = false
126
+ python-versions = "*"
127
+
128
+ [[package]]
129
+ name = "flask"
130
+ version = "2.0.2"
131
+ description = "A simple framework for building complex web applications."
132
+ category = "main"
133
+ optional = false
134
+ python-versions = ">=3.6"
135
+
136
+ [package.dependencies]
137
+ click = ">=7.1.2"
138
+ itsdangerous = ">=2.0"
139
+ Jinja2 = ">=3.0"
140
+ Werkzeug = ">=2.0"
141
+
142
+ [package.extras]
143
+ async = ["asgiref (>=3.2)"]
144
+ dotenv = ["python-dotenv"]
145
+
146
+ [[package]]
147
+ name = "flask-cachebuster"
148
+ version = "1.0.0"
149
+ description = "Flask-CacheBuster is a lightweight Flask extension that adds a hash to the URL query parameters of each static file."
150
+ category = "main"
151
+ optional = false
152
+ python-versions = "*"
153
+
154
+ [package.dependencies]
155
+ Flask = "*"
156
+
157
+ [[package]]
158
+ name = "flask-cors"
159
+ version = "3.0.10"
160
+ description = "A Flask extension adding a decorator for CORS support"
161
+ category = "main"
162
+ optional = false
163
+ python-versions = "*"
164
+
165
+ [package.dependencies]
166
+ Flask = ">=0.9"
167
+ Six = "*"
168
+
169
+ [[package]]
170
+ name = "flask-login"
171
+ version = "0.5.0"
172
+ description = "User session management for Flask"
173
+ category = "main"
174
+ optional = false
175
+ python-versions = "*"
176
+
177
+ [package.dependencies]
178
+ Flask = "*"
179
+
180
+ [[package]]
181
+ name = "fonttools"
182
+ version = "4.28.5"
183
+ description = "Tools to manipulate font files"
184
+ category = "main"
185
+ optional = false
186
+ python-versions = ">=3.7"
187
+
188
+ [package.extras]
189
+ all = ["fs (>=2.2.0,<3)", "lxml (>=4.0,<5)", "zopfli (>=0.1.4)", "lz4 (>=1.7.4.2)", "matplotlib", "sympy", "skia-pathops (>=0.5.0)", "brotlicffi (>=0.8.0)", "scipy", "brotli (>=1.0.1)", "munkres", "unicodedata2 (>=13.0.0)", "xattr"]
190
+ graphite = ["lz4 (>=1.7.4.2)"]
191
+ interpolatable = ["scipy", "munkres"]
192
+ lxml = ["lxml (>=4.0,<5)"]
193
+ pathops = ["skia-pathops (>=0.5.0)"]
194
+ plot = ["matplotlib"]
195
+ symfont = ["sympy"]
196
+ type1 = ["xattr"]
197
+ ufo = ["fs (>=2.2.0,<3)"]
198
+ unicode = ["unicodedata2 (>=13.0.0)"]
199
+ woff = ["zopfli (>=0.1.4)", "brotlicffi (>=0.8.0)", "brotli (>=1.0.1)"]
200
+
201
+ [[package]]
202
+ name = "gradio"
203
+ version = "2.5.3"
204
+ description = "Python library for easily interacting with trained machine learning models"
205
+ category = "main"
206
+ optional = false
207
+ python-versions = "*"
208
+
209
+ [package.dependencies]
210
+ analytics-python = "*"
211
+ ffmpy = "*"
212
+ Flask = ">=1.1.1"
213
+ flask-cachebuster = "*"
214
+ Flask-Cors = ">=3.0.8"
215
+ Flask-Login = "*"
216
+ markdown2 = "*"
217
+ matplotlib = "*"
218
+ numpy = "*"
219
+ pandas = "*"
220
+ paramiko = "*"
221
+ pillow = "*"
222
+ pycryptodome = "*"
223
+ pydub = "*"
224
+ requests = "*"
225
+
226
+ [[package]]
227
+ name = "idna"
228
+ version = "3.3"
229
+ description = "Internationalized Domain Names in Applications (IDNA)"
230
+ category = "main"
231
+ optional = false
232
+ python-versions = ">=3.5"
233
+
234
+ [[package]]
235
+ name = "importlib-metadata"
236
+ version = "4.10.0"
237
+ description = "Read metadata from Python packages"
238
+ category = "main"
239
+ optional = false
240
+ python-versions = ">=3.7"
241
+
242
+ [package.dependencies]
243
+ typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""}
244
+ zipp = ">=0.5"
245
+
246
+ [package.extras]
247
+ docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"]
248
+ perf = ["ipython"]
249
+ testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"]
250
+
251
+ [[package]]
252
+ name = "itsdangerous"
253
+ version = "2.0.1"
254
+ description = "Safely pass data to untrusted environments and back."
255
+ category = "main"
256
+ optional = false
257
+ python-versions = ">=3.6"
258
+
259
+ [[package]]
260
+ name = "jinja2"
261
+ version = "3.0.3"
262
+ description = "A very fast and expressive template engine."
263
+ category = "main"
264
+ optional = false
265
+ python-versions = ">=3.6"
266
+
267
+ [package.dependencies]
268
+ MarkupSafe = ">=2.0"
269
+
270
+ [package.extras]
271
+ i18n = ["Babel (>=2.7)"]
272
+
273
+ [[package]]
274
+ name = "kiwisolver"
275
+ version = "1.3.2"
276
+ description = "A fast implementation of the Cassowary constraint solver"
277
+ category = "main"
278
+ optional = false
279
+ python-versions = ">=3.7"
280
+
281
+ [[package]]
282
+ name = "markdown2"
283
+ version = "2.4.2"
284
+ description = "A fast and complete Python implementation of Markdown"
285
+ category = "main"
286
+ optional = false
287
+ python-versions = ">=3.5, <4"
288
+
289
+ [[package]]
290
+ name = "markupsafe"
291
+ version = "2.0.1"
292
+ description = "Safely add untrusted strings to HTML/XML markup."
293
+ category = "main"
294
+ optional = false
295
+ python-versions = ">=3.6"
296
+
297
+ [[package]]
298
+ name = "matplotlib"
299
+ version = "3.5.1"
300
+ description = "Python plotting package"
301
+ category = "main"
302
+ optional = false
303
+ python-versions = ">=3.7"
304
+
305
+ [package.dependencies]
306
+ cycler = ">=0.10"
307
+ fonttools = ">=4.22.0"
308
+ kiwisolver = ">=1.0.1"
309
+ numpy = ">=1.17"
310
+ packaging = ">=20.0"
311
+ pillow = ">=6.2.0"
312
+ pyparsing = ">=2.2.1"
313
+ python-dateutil = ">=2.7"
314
+ setuptools_scm = ">=4"
315
+
316
+ [[package]]
317
+ name = "monotonic"
318
+ version = "1.6"
319
+ description = "An implementation of time.monotonic() for Python 2 & < 3.3"
320
+ category = "main"
321
+ optional = false
322
+ python-versions = "*"
323
+
324
+ [[package]]
325
+ name = "numpy"
326
+ version = "1.21.1"
327
+ description = "NumPy is the fundamental package for array computing with Python."
328
+ category = "main"
329
+ optional = false
330
+ python-versions = ">=3.7"
331
+
332
+ [[package]]
333
+ name = "packaging"
334
+ version = "21.3"
335
+ description = "Core utilities for Python packages"
336
+ category = "main"
337
+ optional = false
338
+ python-versions = ">=3.6"
339
+
340
+ [package.dependencies]
341
+ pyparsing = ">=2.0.2,<3.0.5 || >3.0.5"
342
+
343
+ [[package]]
344
+ name = "pandas"
345
+ version = "1.1.5"
346
+ description = "Powerful data structures for data analysis, time series, and statistics"
347
+ category = "main"
348
+ optional = false
349
+ python-versions = ">=3.6.1"
350
+
351
+ [package.dependencies]
352
+ numpy = ">=1.15.4"
353
+ python-dateutil = ">=2.7.3"
354
+ pytz = ">=2017.2"
355
+
356
+ [package.extras]
357
+ test = ["pytest (>=4.0.2)", "pytest-xdist", "hypothesis (>=3.58)"]
358
+
359
+ [[package]]
360
+ name = "paramiko"
361
+ version = "2.8.1"
362
+ description = "SSH2 protocol library"
363
+ category = "main"
364
+ optional = false
365
+ python-versions = "*"
366
+
367
+ [package.dependencies]
368
+ bcrypt = ">=3.1.3"
369
+ cryptography = ">=2.5"
370
+ pynacl = ">=1.0.1"
371
+
372
+ [package.extras]
373
+ all = ["pyasn1 (>=0.1.7)", "pynacl (>=1.0.1)", "bcrypt (>=3.1.3)", "invoke (>=1.3)", "gssapi (>=1.4.1)", "pywin32 (>=2.1.8)"]
374
+ ed25519 = ["pynacl (>=1.0.1)", "bcrypt (>=3.1.3)"]
375
+ gssapi = ["pyasn1 (>=0.1.7)", "gssapi (>=1.4.1)", "pywin32 (>=2.1.8)"]
376
+ invoke = ["invoke (>=1.3)"]
377
+
378
+ [[package]]
379
+ name = "pillow"
380
+ version = "8.4.0"
381
+ description = "Python Imaging Library (Fork)"
382
+ category = "main"
383
+ optional = false
384
+ python-versions = ">=3.6"
385
+
386
+ [[package]]
387
+ name = "pycparser"
388
+ version = "2.21"
389
+ description = "C parser in Python"
390
+ category = "main"
391
+ optional = false
392
+ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
393
+
394
+ [[package]]
395
+ name = "pycryptodome"
396
+ version = "3.12.0"
397
+ description = "Cryptographic library for Python"
398
+ category = "main"
399
+ optional = false
400
+ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
401
+
402
+ [[package]]
403
+ name = "pydub"
404
+ version = "0.25.1"
405
+ description = "Manipulate audio with an simple and easy high level interface"
406
+ category = "main"
407
+ optional = false
408
+ python-versions = "*"
409
+
410
+ [[package]]
411
+ name = "pynacl"
412
+ version = "1.4.0"
413
+ description = "Python binding to the Networking and Cryptography (NaCl) library"
414
+ category = "main"
415
+ optional = false
416
+ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
417
+
418
+ [package.dependencies]
419
+ cffi = ">=1.4.1"
420
+ six = "*"
421
+
422
+ [package.extras]
423
+ docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"]
424
+ tests = ["pytest (>=3.2.1,!=3.3.0)", "hypothesis (>=3.27.0)"]
425
+
426
+ [[package]]
427
+ name = "pyparsing"
428
+ version = "3.0.6"
429
+ description = "Python parsing module"
430
+ category = "main"
431
+ optional = false
432
+ python-versions = ">=3.6"
433
+
434
+ [package.extras]
435
+ diagrams = ["jinja2", "railroad-diagrams"]
436
+
437
+ [[package]]
438
+ name = "python-dateutil"
439
+ version = "2.8.2"
440
+ description = "Extensions to the standard Python datetime module"
441
+ category = "main"
442
+ optional = false
443
+ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
444
+
445
+ [package.dependencies]
446
+ six = ">=1.5"
447
+
448
+ [[package]]
449
+ name = "pytz"
450
+ version = "2021.3"
451
+ description = "World timezone definitions, modern and historical"
452
+ category = "main"
453
+ optional = false
454
+ python-versions = "*"
455
+
456
+ [[package]]
457
+ name = "requests"
458
+ version = "2.26.0"
459
+ description = "Python HTTP for Humans."
460
+ category = "main"
461
+ optional = false
462
+ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
463
+
464
+ [package.dependencies]
465
+ certifi = ">=2017.4.17"
466
+ charset-normalizer = {version = ">=2.0.0,<2.1.0", markers = "python_version >= \"3\""}
467
+ idna = {version = ">=2.5,<4", markers = "python_version >= \"3\""}
468
+ urllib3 = ">=1.21.1,<1.27"
469
+
470
+ [package.extras]
471
+ socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"]
472
+ use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"]
473
+
474
+ [[package]]
475
+ name = "setuptools-scm"
476
+ version = "6.3.2"
477
+ description = "the blessed package to manage your versions by scm tags"
478
+ category = "main"
479
+ optional = false
480
+ python-versions = ">=3.6"
481
+
482
+ [package.dependencies]
483
+ packaging = ">=20.0"
484
+ tomli = ">=1.0.0"
485
+
486
+ [package.extras]
487
+ toml = ["setuptools (>=42)", "tomli (>=1.0.0)"]
488
+
489
+ [[package]]
490
+ name = "six"
491
+ version = "1.16.0"
492
+ description = "Python 2 and 3 compatibility utilities"
493
+ category = "main"
494
+ optional = false
495
+ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
496
+
497
+ [[package]]
498
+ name = "tomli"
499
+ version = "2.0.0"
500
+ description = "A lil' TOML parser"
501
+ category = "main"
502
+ optional = false
503
+ python-versions = ">=3.7"
504
+
505
+ [[package]]
506
+ name = "typing-extensions"
507
+ version = "4.0.1"
508
+ description = "Backported and Experimental Type Hints for Python 3.6+"
509
+ category = "main"
510
+ optional = false
511
+ python-versions = ">=3.6"
512
+
513
+ [[package]]
514
+ name = "urllib3"
515
+ version = "1.26.7"
516
+ description = "HTTP library with thread-safe connection pooling, file post, and more."
517
+ category = "main"
518
+ optional = false
519
+ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4"
520
+
521
+ [package.extras]
522
+ brotli = ["brotlipy (>=0.6.0)"]
523
+ secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"]
524
+ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
525
+
526
+ [[package]]
527
+ name = "werkzeug"
528
+ version = "2.0.2"
529
+ description = "The comprehensive WSGI web application library."
530
+ category = "main"
531
+ optional = false
532
+ python-versions = ">=3.6"
533
+
534
+ [package.extras]
535
+ watchdog = ["watchdog"]
536
+
537
+ [[package]]
538
+ name = "zipp"
539
+ version = "3.6.0"
540
+ description = "Backport of pathlib-compatible object wrapper for zip files"
541
+ category = "main"
542
+ optional = false
543
+ python-versions = ">=3.6"
544
+
545
+ [package.extras]
546
+ docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"]
547
+ testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"]
548
+
549
+ [metadata]
550
+ lock-version = "1.1"
551
+ python-versions = "^3.7"
552
+ content-hash = "f908cb0279ff9f36e0fba67bfc362fe26476b024196fc901362b6fa91fc04364"
553
+
554
+ [metadata.files]
555
+ analytics-python = [
556
+ {file = "analytics-python-1.4.0.tar.gz", hash = "sha256:a65141ab6e47db396f5bc5708b1db93ff9a99882d81fe808228afd5ebb6dfe5f"},
557
+ {file = "analytics_python-1.4.0-py2.py3-none-any.whl", hash = "sha256:3bff972beeb8a3f26607ccd9153484aa4f12eeeea4a693be685bf45aa66ddf99"},
558
+ ]
559
+ backoff = [
560
+ {file = "backoff-1.10.0-py2.py3-none-any.whl", hash = "sha256:5e73e2cbe780e1915a204799dba0a01896f45f4385e636bcca7a0614d879d0cd"},
561
+ {file = "backoff-1.10.0.tar.gz", hash = "sha256:b8fba021fac74055ac05eb7c7bfce4723aedde6cd0a504e5326bcb0bdd6d19a4"},
562
+ ]
563
+ bcrypt = [
564
+ {file = "bcrypt-3.2.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c95d4cbebffafcdd28bd28bb4e25b31c50f6da605c81ffd9ad8a3d1b2ab7b1b6"},
565
+ {file = "bcrypt-3.2.0-cp36-abi3-manylinux1_x86_64.whl", hash = "sha256:63d4e3ff96188e5898779b6057878fecf3f11cfe6ec3b313ea09955d587ec7a7"},
566
+ {file = "bcrypt-3.2.0-cp36-abi3-manylinux2010_x86_64.whl", hash = "sha256:cd1ea2ff3038509ea95f687256c46b79f5fc382ad0aa3664d200047546d511d1"},
567
+ {file = "bcrypt-3.2.0-cp36-abi3-manylinux2014_aarch64.whl", hash = "sha256:cdcdcb3972027f83fe24a48b1e90ea4b584d35f1cc279d76de6fc4b13376239d"},
568
+ {file = "bcrypt-3.2.0-cp36-abi3-win32.whl", hash = "sha256:a67fb841b35c28a59cebed05fbd3e80eea26e6d75851f0574a9273c80f3e9b55"},
569
+ {file = "bcrypt-3.2.0-cp36-abi3-win_amd64.whl", hash = "sha256:81fec756feff5b6818ea7ab031205e1d323d8943d237303baca2c5f9c7846f34"},
570
+ {file = "bcrypt-3.2.0.tar.gz", hash = "sha256:5b93c1726e50a93a033c36e5ca7fdcd29a5c7395af50a6892f5d9e7c6cfbfb29"},
571
+ ]
572
+ certifi = [
573
+ {file = "certifi-2021.10.8-py2.py3-none-any.whl", hash = "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"},
574
+ {file = "certifi-2021.10.8.tar.gz", hash = "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872"},
575
+ ]
576
+ cffi = [
577
+ {file = "cffi-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:c2502a1a03b6312837279c8c1bd3ebedf6c12c4228ddbad40912d671ccc8a962"},
578
+ {file = "cffi-1.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:23cfe892bd5dd8941608f93348c0737e369e51c100d03718f108bf1add7bd6d0"},
579
+ {file = "cffi-1.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:41d45de54cd277a7878919867c0f08b0cf817605e4eb94093e7516505d3c8d14"},
580
+ {file = "cffi-1.15.0-cp27-cp27m-win32.whl", hash = "sha256:4a306fa632e8f0928956a41fa8e1d6243c71e7eb59ffbd165fc0b41e316b2474"},
581
+ {file = "cffi-1.15.0-cp27-cp27m-win_amd64.whl", hash = "sha256:e7022a66d9b55e93e1a845d8c9eba2a1bebd4966cd8bfc25d9cd07d515b33fa6"},
582
+ {file = "cffi-1.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:14cd121ea63ecdae71efa69c15c5543a4b5fbcd0bbe2aad864baca0063cecf27"},
583
+ {file = "cffi-1.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:d4d692a89c5cf08a8557fdeb329b82e7bf609aadfaed6c0d79f5a449a3c7c023"},
584
+ {file = "cffi-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0104fb5ae2391d46a4cb082abdd5c69ea4eab79d8d44eaaf79f1b1fd806ee4c2"},
585
+ {file = "cffi-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:91ec59c33514b7c7559a6acda53bbfe1b283949c34fe7440bcf917f96ac0723e"},
586
+ {file = "cffi-1.15.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f5c7150ad32ba43a07c4479f40241756145a1f03b43480e058cfd862bf5041c7"},
587
+ {file = "cffi-1.15.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:00c878c90cb53ccfaae6b8bc18ad05d2036553e6d9d1d9dbcf323bbe83854ca3"},
588
+ {file = "cffi-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abb9a20a72ac4e0fdb50dae135ba5e77880518e742077ced47eb1499e29a443c"},
589
+ {file = "cffi-1.15.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a5263e363c27b653a90078143adb3d076c1a748ec9ecc78ea2fb916f9b861962"},
590
+ {file = "cffi-1.15.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f54a64f8b0c8ff0b64d18aa76675262e1700f3995182267998c31ae974fbc382"},
591
+ {file = "cffi-1.15.0-cp310-cp310-win32.whl", hash = "sha256:c21c9e3896c23007803a875460fb786118f0cdd4434359577ea25eb556e34c55"},
592
+ {file = "cffi-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:5e069f72d497312b24fcc02073d70cb989045d1c91cbd53979366077959933e0"},
593
+ {file = "cffi-1.15.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:64d4ec9f448dfe041705426000cc13e34e6e5bb13736e9fd62e34a0b0c41566e"},
594
+ {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2756c88cbb94231c7a147402476be2c4df2f6078099a6f4a480d239a8817ae39"},
595
+ {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b96a311ac60a3f6be21d2572e46ce67f09abcf4d09344c49274eb9e0bf345fc"},
596
+ {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75e4024375654472cc27e91cbe9eaa08567f7fbdf822638be2814ce059f58032"},
597
+ {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:59888172256cac5629e60e72e86598027aca6bf01fa2465bdb676d37636573e8"},
598
+ {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:27c219baf94952ae9d50ec19651a687b826792055353d07648a5695413e0c605"},
599
+ {file = "cffi-1.15.0-cp36-cp36m-win32.whl", hash = "sha256:4958391dbd6249d7ad855b9ca88fae690783a6be9e86df65865058ed81fc860e"},
600
+ {file = "cffi-1.15.0-cp36-cp36m-win_amd64.whl", hash = "sha256:f6f824dc3bce0edab5f427efcfb1d63ee75b6fcb7282900ccaf925be84efb0fc"},
601
+ {file = "cffi-1.15.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:06c48159c1abed75c2e721b1715c379fa3200c7784271b3c46df01383b593636"},
602
+ {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c2051981a968d7de9dd2d7b87bcb9c939c74a34626a6e2f8181455dd49ed69e4"},
603
+ {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:fd8a250edc26254fe5b33be00402e6d287f562b6a5b2152dec302fa15bb3e997"},
604
+ {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91d77d2a782be4274da750752bb1650a97bfd8f291022b379bb8e01c66b4e96b"},
605
+ {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:45db3a33139e9c8f7c09234b5784a5e33d31fd6907800b316decad50af323ff2"},
606
+ {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:263cc3d821c4ab2213cbe8cd8b355a7f72a8324577dc865ef98487c1aeee2bc7"},
607
+ {file = "cffi-1.15.0-cp37-cp37m-win32.whl", hash = "sha256:17771976e82e9f94976180f76468546834d22a7cc404b17c22df2a2c81db0c66"},
608
+ {file = "cffi-1.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:3415c89f9204ee60cd09b235810be700e993e343a408693e80ce7f6a40108029"},
609
+ {file = "cffi-1.15.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4238e6dab5d6a8ba812de994bbb0a79bddbdf80994e4ce802b6f6f3142fcc880"},
610
+ {file = "cffi-1.15.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0808014eb713677ec1292301ea4c81ad277b6cdf2fdd90fd540af98c0b101d20"},
611
+ {file = "cffi-1.15.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:57e9ac9ccc3101fac9d6014fba037473e4358ef4e89f8e181f8951a2c0162024"},
612
+ {file = "cffi-1.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b6c2ea03845c9f501ed1313e78de148cd3f6cad741a75d43a29b43da27f2e1e"},
613
+ {file = "cffi-1.15.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:10dffb601ccfb65262a27233ac273d552ddc4d8ae1bf93b21c94b8511bffe728"},
614
+ {file = "cffi-1.15.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:786902fb9ba7433aae840e0ed609f45c7bcd4e225ebb9c753aa39725bb3e6ad6"},
615
+ {file = "cffi-1.15.0-cp38-cp38-win32.whl", hash = "sha256:da5db4e883f1ce37f55c667e5c0de439df76ac4cb55964655906306918e7363c"},
616
+ {file = "cffi-1.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:181dee03b1170ff1969489acf1c26533710231c58f95534e3edac87fff06c443"},
617
+ {file = "cffi-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:45e8636704eacc432a206ac7345a5d3d2c62d95a507ec70d62f23cd91770482a"},
618
+ {file = "cffi-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:31fb708d9d7c3f49a60f04cf5b119aeefe5644daba1cd2a0fe389b674fd1de37"},
619
+ {file = "cffi-1.15.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6dc2737a3674b3e344847c8686cf29e500584ccad76204efea14f451d4cc669a"},
620
+ {file = "cffi-1.15.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:74fdfdbfdc48d3f47148976f49fab3251e550a8720bebc99bf1483f5bfb5db3e"},
621
+ {file = "cffi-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffaa5c925128e29efbde7301d8ecaf35c8c60ffbcd6a1ffd3a552177c8e5e796"},
622
+ {file = "cffi-1.15.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f7d084648d77af029acb79a0ff49a0ad7e9d09057a9bf46596dac9514dc07df"},
623
+ {file = "cffi-1.15.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ef1f279350da2c586a69d32fc8733092fd32cc8ac95139a00377841f59a3f8d8"},
624
+ {file = "cffi-1.15.0-cp39-cp39-win32.whl", hash = "sha256:2a23af14f408d53d5e6cd4e3d9a24ff9e05906ad574822a10563efcef137979a"},
625
+ {file = "cffi-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:3773c4d81e6e818df2efbc7dd77325ca0dcb688116050fb2b3011218eda36139"},
626
+ {file = "cffi-1.15.0.tar.gz", hash = "sha256:920f0d66a896c2d99f0adbb391f990a84091179542c205fa53ce5787aff87954"},
627
+ ]
628
+ charset-normalizer = [
629
+ {file = "charset-normalizer-2.0.9.tar.gz", hash = "sha256:b0b883e8e874edfdece9c28f314e3dd5badf067342e42fb162203335ae61aa2c"},
630
+ {file = "charset_normalizer-2.0.9-py3-none-any.whl", hash = "sha256:1eecaa09422db5be9e29d7fc65664e6c33bd06f9ced7838578ba40d58bdf3721"},
631
+ ]
632
+ click = [
633
+ {file = "click-8.0.3-py3-none-any.whl", hash = "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3"},
634
+ {file = "click-8.0.3.tar.gz", hash = "sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b"},
635
+ ]
636
+ colorama = [
637
+ {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
638
+ {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
639
+ ]
640
+ cryptography = [
641
+ {file = "cryptography-36.0.1-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:73bc2d3f2444bcfeac67dd130ff2ea598ea5f20b40e36d19821b4df8c9c5037b"},
642
+ {file = "cryptography-36.0.1-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:2d87cdcb378d3cfed944dac30596da1968f88fb96d7fc34fdae30a99054b2e31"},
643
+ {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:74d6c7e80609c0f4c2434b97b80c7f8fdfaa072ca4baab7e239a15d6d70ed73a"},
644
+ {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:6c0c021f35b421ebf5976abf2daacc47e235f8b6082d3396a2fe3ccd537ab173"},
645
+ {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d59a9d55027a8b88fd9fd2826c4392bd487d74bf628bb9d39beecc62a644c12"},
646
+ {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a817b961b46894c5ca8a66b599c745b9a3d9f822725221f0e0fe49dc043a3a3"},
647
+ {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:94ae132f0e40fe48f310bba63f477f14a43116f05ddb69d6fa31e93f05848ae2"},
648
+ {file = "cryptography-36.0.1-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:7be0eec337359c155df191d6ae00a5e8bbb63933883f4f5dffc439dac5348c3f"},
649
+ {file = "cryptography-36.0.1-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:e0344c14c9cb89e76eb6a060e67980c9e35b3f36691e15e1b7a9e58a0a6c6dc3"},
650
+ {file = "cryptography-36.0.1-cp36-abi3-win32.whl", hash = "sha256:4caa4b893d8fad33cf1964d3e51842cd78ba87401ab1d2e44556826df849a8ca"},
651
+ {file = "cryptography-36.0.1-cp36-abi3-win_amd64.whl", hash = "sha256:391432971a66cfaf94b21c24ab465a4cc3e8bf4a939c1ca5c3e3a6e0abebdbcf"},
652
+ {file = "cryptography-36.0.1-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:bb5829d027ff82aa872d76158919045a7c1e91fbf241aec32cb07956e9ebd3c9"},
653
+ {file = "cryptography-36.0.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ebc15b1c22e55c4d5566e3ca4db8689470a0ca2babef8e3a9ee057a8b82ce4b1"},
654
+ {file = "cryptography-36.0.1-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:596f3cd67e1b950bc372c33f1a28a0692080625592ea6392987dba7f09f17a94"},
655
+ {file = "cryptography-36.0.1-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:30ee1eb3ebe1644d1c3f183d115a8c04e4e603ed6ce8e394ed39eea4a98469ac"},
656
+ {file = "cryptography-36.0.1-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ec63da4e7e4a5f924b90af42eddf20b698a70e58d86a72d943857c4c6045b3ee"},
657
+ {file = "cryptography-36.0.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca238ceb7ba0bdf6ce88c1b74a87bffcee5afbfa1e41e173b1ceb095b39add46"},
658
+ {file = "cryptography-36.0.1-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:ca28641954f767f9822c24e927ad894d45d5a1e501767599647259cbf030b903"},
659
+ {file = "cryptography-36.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:39bdf8e70eee6b1c7b289ec6e5d84d49a6bfa11f8b8646b5b3dfe41219153316"},
660
+ {file = "cryptography-36.0.1.tar.gz", hash = "sha256:53e5c1dc3d7a953de055d77bef2ff607ceef7a2aac0353b5d630ab67f7423638"},
661
+ ]
662
+ cycler = [
663
+ {file = "cycler-0.11.0-py3-none-any.whl", hash = "sha256:3a27e95f763a428a739d2add979fa7494c912a32c17c4c38c4d5f082cad165a3"},
664
+ {file = "cycler-0.11.0.tar.gz", hash = "sha256:9c87405839a19696e837b3b818fed3f5f69f16f1eec1a1ad77e043dcea9c772f"},
665
+ ]
666
+ ffmpy = [
667
+ {file = "ffmpy-0.3.0.tar.gz", hash = "sha256:757591581eee25b4a50ac9ffb9b58035a2794533db47e0512f53fb2d7b6f9adc"},
668
+ ]
669
+ flask = [
670
+ {file = "Flask-2.0.2-py3-none-any.whl", hash = "sha256:cb90f62f1d8e4dc4621f52106613488b5ba826b2e1e10a33eac92f723093ab6a"},
671
+ {file = "Flask-2.0.2.tar.gz", hash = "sha256:7b2fb8e934ddd50731893bdcdb00fc8c0315916f9fcd50d22c7cc1a95ab634e2"},
672
+ ]
673
+ flask-cachebuster = [
674
+ {file = "Flask-CacheBuster-1.0.0.tar.gz", hash = "sha256:0c8d7b57db8953f5c5875153f16cb970c2ed5a681b39326613c822f0c9764ec8"},
675
+ ]
676
+ flask-cors = [
677
+ {file = "Flask-Cors-3.0.10.tar.gz", hash = "sha256:b60839393f3b84a0f3746f6cdca56c1ad7426aa738b70d6c61375857823181de"},
678
+ {file = "Flask_Cors-3.0.10-py2.py3-none-any.whl", hash = "sha256:74efc975af1194fc7891ff5cd85b0f7478be4f7f59fe158102e91abb72bb4438"},
679
+ ]
680
+ flask-login = [
681
+ {file = "Flask-Login-0.5.0.tar.gz", hash = "sha256:6d33aef15b5bcead780acc339464aae8a6e28f13c90d8b1cf9de8b549d1c0b4b"},
682
+ {file = "Flask_Login-0.5.0-py2.py3-none-any.whl", hash = "sha256:7451b5001e17837ba58945aead261ba425fdf7b4f0448777e597ddab39f4fba0"},
683
+ ]
684
+ fonttools = [
685
+ {file = "fonttools-4.28.5-py3-none-any.whl", hash = "sha256:edf251d5d2cc0580d5f72de4621c338d8c66c5f61abb50cf486640f73c8194d5"},
686
+ {file = "fonttools-4.28.5.zip", hash = "sha256:545c05d0f7903a863c2020e07b8f0a57517f2c40d940bded77076397872d14ca"},
687
+ ]
688
+ gradio = [
689
+ {file = "gradio-2.5.3-py3-none-any.whl", hash = "sha256:4b5769cecc321507894c253638f5afaf3dd0d40b0dbd5caaa67631a2076c0d5d"},
690
+ {file = "gradio-2.5.3.tar.gz", hash = "sha256:bc6e7bea8918cdb0891b687ada8a4b171a985b8ab2f784b06c677c33d99feebd"},
691
+ ]
692
+ idna = [
693
+ {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"},
694
+ {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"},
695
+ ]
696
+ importlib-metadata = [
697
+ {file = "importlib_metadata-4.10.0-py3-none-any.whl", hash = "sha256:b7cf7d3fef75f1e4c80a96ca660efbd51473d7e8f39b5ab9210febc7809012a4"},
698
+ {file = "importlib_metadata-4.10.0.tar.gz", hash = "sha256:92a8b58ce734b2a4494878e0ecf7d79ccd7a128b5fc6014c401e0b61f006f0f6"},
699
+ ]
700
+ itsdangerous = [
701
+ {file = "itsdangerous-2.0.1-py3-none-any.whl", hash = "sha256:5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c"},
702
+ {file = "itsdangerous-2.0.1.tar.gz", hash = "sha256:9e724d68fc22902a1435351f84c3fb8623f303fffcc566a4cb952df8c572cff0"},
703
+ ]
704
+ jinja2 = [
705
+ {file = "Jinja2-3.0.3-py3-none-any.whl", hash = "sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8"},
706
+ {file = "Jinja2-3.0.3.tar.gz", hash = "sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7"},
707
+ ]
708
+ kiwisolver = [
709
+ {file = "kiwisolver-1.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1d819553730d3c2724582124aee8a03c846ec4362ded1034c16fb3ef309264e6"},
710
+ {file = "kiwisolver-1.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8d93a1095f83e908fc253f2fb569c2711414c0bfd451cab580466465b235b470"},
711
+ {file = "kiwisolver-1.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4550a359c5157aaf8507e6820d98682872b9100ce7607f8aa070b4b8af6c298"},
712
+ {file = "kiwisolver-1.3.2-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2210f28778c7d2ee13f3c2a20a3a22db889e75f4ec13a21072eabb5693801e84"},
713
+ {file = "kiwisolver-1.3.2-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:82f49c5a79d3839bc8f38cb5f4bfc87e15f04cbafa5fbd12fb32c941cb529cfb"},
714
+ {file = "kiwisolver-1.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9661a04ca3c950a8ac8c47f53cbc0b530bce1b52f516a1e87b7736fec24bfff0"},
715
+ {file = "kiwisolver-1.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2ddb500a2808c100e72c075cbb00bf32e62763c82b6a882d403f01a119e3f402"},
716
+ {file = "kiwisolver-1.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:72be6ebb4e92520b9726d7146bc9c9b277513a57a38efcf66db0620aec0097e0"},
717
+ {file = "kiwisolver-1.3.2-cp310-cp310-win32.whl", hash = "sha256:83d2c9db5dfc537d0171e32de160461230eb14663299b7e6d18ca6dca21e4977"},
718
+ {file = "kiwisolver-1.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:cba430db673c29376135e695c6e2501c44c256a81495da849e85d1793ee975ad"},
719
+ {file = "kiwisolver-1.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4116ba9a58109ed5e4cb315bdcbff9838f3159d099ba5259c7c7fb77f8537492"},
720
+ {file = "kiwisolver-1.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19554bd8d54cf41139f376753af1a644b63c9ca93f8f72009d50a2080f870f77"},
721
+ {file = "kiwisolver-1.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a7a4cf5bbdc861987a7745aed7a536c6405256853c94abc9f3287c3fa401b174"},
722
+ {file = "kiwisolver-1.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0007840186bacfaa0aba4466d5890334ea5938e0bb7e28078a0eb0e63b5b59d5"},
723
+ {file = "kiwisolver-1.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ec2eba188c1906b05b9b49ae55aae4efd8150c61ba450e6721f64620c50b59eb"},
724
+ {file = "kiwisolver-1.3.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:3dbb3cea20b4af4f49f84cffaf45dd5f88e8594d18568e0225e6ad9dec0e7967"},
725
+ {file = "kiwisolver-1.3.2-cp37-cp37m-win32.whl", hash = "sha256:5326ddfacbe51abf9469fe668944bc2e399181a2158cb5d45e1d40856b2a0589"},
726
+ {file = "kiwisolver-1.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:c6572c2dab23c86a14e82c245473d45b4c515314f1f859e92608dcafbd2f19b8"},
727
+ {file = "kiwisolver-1.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b5074fb09429f2b7bc82b6fb4be8645dcbac14e592128beeff5461dcde0af09f"},
728
+ {file = "kiwisolver-1.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:22521219ca739654a296eea6d4367703558fba16f98688bd8ce65abff36eaa84"},
729
+ {file = "kiwisolver-1.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c358721aebd40c243894298f685a19eb0491a5c3e0b923b9f887ef1193ddf829"},
730
+ {file = "kiwisolver-1.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ba5a1041480c6e0a8b11a9544d53562abc2d19220bfa14133e0cdd9967e97af"},
731
+ {file = "kiwisolver-1.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:44e6adf67577dbdfa2d9f06db9fbc5639afefdb5bf2b4dfec25c3a7fbc619536"},
732
+ {file = "kiwisolver-1.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1d45d1c74f88b9f41062716c727f78f2a59a5476ecbe74956fafb423c5c87a76"},
733
+ {file = "kiwisolver-1.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:70adc3658138bc77a36ce769f5f183169bc0a2906a4f61f09673f7181255ac9b"},
734
+ {file = "kiwisolver-1.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:b6a5431940f28b6de123de42f0eb47b84a073ee3c3345dc109ad550a3307dd28"},
735
+ {file = "kiwisolver-1.3.2-cp38-cp38-win32.whl", hash = "sha256:ee040a7de8d295dbd261ef2d6d3192f13e2b08ec4a954de34a6fb8ff6422e24c"},
736
+ {file = "kiwisolver-1.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:8dc3d842fa41a33fe83d9f5c66c0cc1f28756530cd89944b63b072281e852031"},
737
+ {file = "kiwisolver-1.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a498bcd005e8a3fedd0022bb30ee0ad92728154a8798b703f394484452550507"},
738
+ {file = "kiwisolver-1.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:80efd202108c3a4150e042b269f7c78643420cc232a0a771743bb96b742f838f"},
739
+ {file = "kiwisolver-1.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f8eb7b6716f5b50e9c06207a14172cf2de201e41912ebe732846c02c830455b9"},
740
+ {file = "kiwisolver-1.3.2-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f441422bb313ab25de7b3dbfd388e790eceb76ce01a18199ec4944b369017009"},
741
+ {file = "kiwisolver-1.3.2-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:30fa008c172355c7768159983a7270cb23838c4d7db73d6c0f6b60dde0d432c6"},
742
+ {file = "kiwisolver-1.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f8f6c8f4f1cff93ca5058d6ec5f0efda922ecb3f4c5fb76181f327decff98b8"},
743
+ {file = "kiwisolver-1.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba677bcaff9429fd1bf01648ad0901cea56c0d068df383d5f5856d88221fe75b"},
744
+ {file = "kiwisolver-1.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7843b1624d6ccca403a610d1277f7c28ad184c5aa88a1750c1a999754e65b439"},
745
+ {file = "kiwisolver-1.3.2-cp39-cp39-win32.whl", hash = "sha256:e6f5eb2f53fac7d408a45fbcdeda7224b1cfff64919d0f95473420a931347ae9"},
746
+ {file = "kiwisolver-1.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:eedd3b59190885d1ebdf6c5e0ca56828beb1949b4dfe6e5d0256a461429ac386"},
747
+ {file = "kiwisolver-1.3.2-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:dedc71c8eb9c5096037766390172c34fb86ef048b8e8958b4e484b9e505d66bc"},
748
+ {file = "kiwisolver-1.3.2-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:bf7eb45d14fc036514c09554bf983f2a72323254912ed0c3c8e697b62c4c158f"},
749
+ {file = "kiwisolver-1.3.2-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2b65bd35f3e06a47b5c30ea99e0c2b88f72c6476eedaf8cfbc8e66adb5479dcf"},
750
+ {file = "kiwisolver-1.3.2-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25405f88a37c5f5bcba01c6e350086d65e7465fd1caaf986333d2a045045a223"},
751
+ {file = "kiwisolver-1.3.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:bcadb05c3d4794eb9eee1dddf1c24215c92fb7b55a80beae7a60530a91060560"},
752
+ {file = "kiwisolver-1.3.2.tar.gz", hash = "sha256:fc4453705b81d03568d5b808ad8f09c77c47534f6ac2e72e733f9ca4714aa75c"},
753
+ ]
754
+ markdown2 = [
755
+ {file = "markdown2-2.4.2-py2.py3-none-any.whl", hash = "sha256:8f4ac8d9a124ab408c67361090ed512deda746c04362c36c2ec16190c720c2b0"},
756
+ {file = "markdown2-2.4.2.tar.gz", hash = "sha256:91113caf23aa662570fe21984f08fe74f814695c0a0ea8e863a8b4c4f63f9f6e"},
757
+ ]
758
+ markupsafe = [
759
+ {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53"},
760
+ {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38"},
761
+ {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad"},
762
+ {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d"},
763
+ {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646"},
764
+ {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4dc8f9fb58f7364b63fd9f85013b780ef83c11857ae79f2feda41e270468dd9b"},
765
+ {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:20dca64a3ef2d6e4d5d615a3fd418ad3bde77a47ec8a23d984a12b5b4c74491a"},
766
+ {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cdfba22ea2f0029c9261a4bd07e830a8da012291fbe44dc794e488b6c9bb353a"},
767
+ {file = "MarkupSafe-2.0.1-cp310-cp310-win32.whl", hash = "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28"},
768
+ {file = "MarkupSafe-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134"},
769
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"},
770
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"},
771
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"},
772
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"},
773
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"},
774
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"},
775
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c"},
776
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724"},
777
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145"},
778
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:deb993cacb280823246a026e3b2d81c493c53de6acfd5e6bfe31ab3402bb37dd"},
779
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:63f3268ba69ace99cab4e3e3b5840b03340efed0948ab8f78d2fd87ee5442a4f"},
780
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:8d206346619592c6200148b01a2142798c989edcb9c896f9ac9722a99d4e77e6"},
781
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"},
782
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"},
783
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"},
784
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18"},
785
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f"},
786
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"},
787
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"},
788
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"},
789
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85"},
790
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6"},
791
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864"},
792
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d6c7ebd4e944c85e2c3421e612a7057a2f48d478d79e61800d81468a8d842207"},
793
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f0567c4dc99f264f49fe27da5f735f414c4e7e7dd850cfd8e69f0862d7c74ea9"},
794
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:89c687013cb1cd489a0f0ac24febe8c7a666e6e221b783e53ac50ebf68e45d86"},
795
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"},
796
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"},
797
+ {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9"},
798
+ {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"},
799
+ {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"},
800
+ {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"},
801
+ {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"},
802
+ {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"},
803
+ {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"},
804
+ {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b"},
805
+ {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a"},
806
+ {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6"},
807
+ {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:aca6377c0cb8a8253e493c6b451565ac77e98c2951c45f913e0b52facdcff83f"},
808
+ {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:04635854b943835a6ea959e948d19dcd311762c5c0c6e1f0e16ee57022669194"},
809
+ {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6300b8454aa6930a24b9618fbb54b5a68135092bc666f7b06901f897fa5c2fee"},
810
+ {file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"},
811
+ {file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"},
812
+ {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"},
813
+ {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7"},
814
+ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8"},
815
+ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5"},
816
+ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"},
817
+ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"},
818
+ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"},
819
+ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1"},
820
+ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac"},
821
+ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6"},
822
+ {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4296f2b1ce8c86a6aea78613c34bb1a672ea0e3de9c6ba08a960efe0b0a09047"},
823
+ {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f02365d4e99430a12647f09b6cc8bab61a6564363f313126f775eb4f6ef798e"},
824
+ {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5b6d930f030f8ed98e3e6c98ffa0652bdb82601e7a016ec2ab5d7ff23baa78d1"},
825
+ {file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"},
826
+ {file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"},
827
+ {file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"},
828
+ ]
829
+ matplotlib = [
830
+ {file = "matplotlib-3.5.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:456cc8334f6d1124e8ff856b42d2cc1c84335375a16448189999496549f7182b"},
831
+ {file = "matplotlib-3.5.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8a77906dc2ef9b67407cec0bdbf08e3971141e535db888974a915be5e1e3efc6"},
832
+ {file = "matplotlib-3.5.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e70ae6475cfd0fad3816dcbf6cac536dc6f100f7474be58d59fa306e6e768a4"},
833
+ {file = "matplotlib-3.5.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:53273c5487d1c19c3bc03b9eb82adaf8456f243b97ed79d09dded747abaf1235"},
834
+ {file = "matplotlib-3.5.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e3b6f3fd0d8ca37861c31e9a7cab71a0ef14c639b4c95654ea1dd153158bf0df"},
835
+ {file = "matplotlib-3.5.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e8c87cdaf06fd7b2477f68909838ff4176f105064a72ca9d24d3f2a29f73d393"},
836
+ {file = "matplotlib-3.5.1-cp310-cp310-win32.whl", hash = "sha256:e2f28a07b4f82abb40267864ad7b3a4ed76f1b1663e81c7efc84a9b9248f672f"},
837
+ {file = "matplotlib-3.5.1-cp310-cp310-win_amd64.whl", hash = "sha256:d70a32ee1f8b55eed3fd4e892f0286df8cccc7e0475c11d33b5d0a148f5c7599"},
838
+ {file = "matplotlib-3.5.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:68fa30cec89b6139dc559ed6ef226c53fd80396da1919a1b5ef672c911aaa767"},
839
+ {file = "matplotlib-3.5.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e3484d8455af3fdb0424eae1789af61f6a79da0c80079125112fd5c1b604218"},
840
+ {file = "matplotlib-3.5.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e293b16cf303fe82995e41700d172a58a15efc5331125d08246b520843ef21ee"},
841
+ {file = "matplotlib-3.5.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:e3520a274a0e054e919f5b3279ee5dbccf5311833819ccf3399dab7c83e90a25"},
842
+ {file = "matplotlib-3.5.1-cp37-cp37m-win32.whl", hash = "sha256:2252bfac85cec7af4a67e494bfccf9080bcba8a0299701eab075f48847cca907"},
843
+ {file = "matplotlib-3.5.1-cp37-cp37m-win_amd64.whl", hash = "sha256:abf67e05a1b7f86583f6ebd01f69b693b9c535276f4e943292e444855870a1b8"},
844
+ {file = "matplotlib-3.5.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6c094e4bfecd2fa7f9adffd03d8abceed7157c928c2976899de282f3600f0a3d"},
845
+ {file = "matplotlib-3.5.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:506b210cc6e66a0d1c2bb765d055f4f6bc2745070fb1129203b67e85bbfa5c18"},
846
+ {file = "matplotlib-3.5.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b04fc29bcef04d4e2d626af28d9d892be6aba94856cb46ed52bcb219ceac8943"},
847
+ {file = "matplotlib-3.5.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:577ed20ec9a18d6bdedb4616f5e9e957b4c08563a9f985563a31fd5b10564d2a"},
848
+ {file = "matplotlib-3.5.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e486f60db0cd1c8d68464d9484fd2a94011c1ac8593d765d0211f9daba2bd535"},
849
+ {file = "matplotlib-3.5.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:b71f3a7ca935fc759f2aed7cec06cfe10bc3100fadb5dbd9c435b04e557971e1"},
850
+ {file = "matplotlib-3.5.1-cp38-cp38-win32.whl", hash = "sha256:d24e5bb8028541ce25e59390122f5e48c8506b7e35587e5135efcb6471b4ac6c"},
851
+ {file = "matplotlib-3.5.1-cp38-cp38-win_amd64.whl", hash = "sha256:778d398c4866d8e36ee3bf833779c940b5f57192fa0a549b3ad67bc4c822771b"},
852
+ {file = "matplotlib-3.5.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bb1c613908f11bac270bc7494d68b1ef6e7c224b7a4204d5dacf3522a41e2bc3"},
853
+ {file = "matplotlib-3.5.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:edf5e4e1d5fb22c18820e8586fb867455de3b109c309cb4fce3aaed85d9468d1"},
854
+ {file = "matplotlib-3.5.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:40e0d7df05e8efe60397c69b467fc8f87a2affeb4d562fe92b72ff8937a2b511"},
855
+ {file = "matplotlib-3.5.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a350ca685d9f594123f652ba796ee37219bf72c8e0fc4b471473d87121d6d34"},
856
+ {file = "matplotlib-3.5.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3e66497cd990b1a130e21919b004da2f1dc112132c01ac78011a90a0f9229778"},
857
+ {file = "matplotlib-3.5.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:87900c67c0f1728e6db17c6809ec05c025c6624dcf96a8020326ea15378fe8e7"},
858
+ {file = "matplotlib-3.5.1-cp39-cp39-win32.whl", hash = "sha256:b8a4fb2a0c5afbe9604f8a91d7d0f27b1832c3e0b5e365f95a13015822b4cd65"},
859
+ {file = "matplotlib-3.5.1-cp39-cp39-win_amd64.whl", hash = "sha256:fe8d40c434a8e2c68d64c6d6a04e77f21791a93ff6afe0dce169597c110d3079"},
860
+ {file = "matplotlib-3.5.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:34a1fc29f8f96e78ec57a5eff5e8d8b53d3298c3be6df61e7aa9efba26929522"},
861
+ {file = "matplotlib-3.5.1-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:b19a761b948e939a9e20173aaae76070025f0024fc8f7ba08bef22a5c8573afc"},
862
+ {file = "matplotlib-3.5.1-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6803299cbf4665eca14428d9e886de62e24f4223ac31ab9c5d6d5339a39782c7"},
863
+ {file = "matplotlib-3.5.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:14334b9902ec776461c4b8c6516e26b450f7ebe0b3ef8703bf5cdfbbaecf774a"},
864
+ {file = "matplotlib-3.5.1.tar.gz", hash = "sha256:b2e9810e09c3a47b73ce9cab5a72243a1258f61e7900969097a817232246ce1c"},
865
+ ]
866
+ monotonic = [
867
+ {file = "monotonic-1.6-py2.py3-none-any.whl", hash = "sha256:68687e19a14f11f26d140dd5c86f3dba4bf5df58003000ed467e0e2a69bca96c"},
868
+ {file = "monotonic-1.6.tar.gz", hash = "sha256:3a55207bcfed53ddd5c5bae174524062935efed17792e9de2ad0205ce9ad63f7"},
869
+ ]
870
+ numpy = [
871
+ {file = "numpy-1.21.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:38e8648f9449a549a7dfe8d8755a5979b45b3538520d1e735637ef28e8c2dc50"},
872
+ {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:fd7d7409fa643a91d0a05c7554dd68aa9c9bb16e186f6ccfe40d6e003156e33a"},
873
+ {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a75b4498b1e93d8b700282dc8e655b8bd559c0904b3910b144646dbbbc03e062"},
874
+ {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1412aa0aec3e00bc23fbb8664d76552b4efde98fb71f60737c83efbac24112f1"},
875
+ {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e46ceaff65609b5399163de5893d8f2a82d3c77d5e56d976c8b5fb01faa6b671"},
876
+ {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:c6a2324085dd52f96498419ba95b5777e40b6bcbc20088fddb9e8cbb58885e8e"},
877
+ {file = "numpy-1.21.1-cp37-cp37m-win32.whl", hash = "sha256:73101b2a1fef16602696d133db402a7e7586654682244344b8329cdcbbb82172"},
878
+ {file = "numpy-1.21.1-cp37-cp37m-win_amd64.whl", hash = "sha256:7a708a79c9a9d26904d1cca8d383bf869edf6f8e7650d85dbc77b041e8c5a0f8"},
879
+ {file = "numpy-1.21.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:95b995d0c413f5d0428b3f880e8fe1660ff9396dcd1f9eedbc311f37b5652e16"},
880
+ {file = "numpy-1.21.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:635e6bd31c9fb3d475c8f44a089569070d10a9ef18ed13738b03049280281267"},
881
+ {file = "numpy-1.21.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4a3d5fb89bfe21be2ef47c0614b9c9c707b7362386c9a3ff1feae63e0267ccb6"},
882
+ {file = "numpy-1.21.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:8a326af80e86d0e9ce92bcc1e65c8ff88297de4fa14ee936cb2293d414c9ec63"},
883
+ {file = "numpy-1.21.1-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:791492091744b0fe390a6ce85cc1bf5149968ac7d5f0477288f78c89b385d9af"},
884
+ {file = "numpy-1.21.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0318c465786c1f63ac05d7c4dbcecd4d2d7e13f0959b01b534ea1e92202235c5"},
885
+ {file = "numpy-1.21.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9a513bd9c1551894ee3d31369f9b07460ef223694098cf27d399513415855b68"},
886
+ {file = "numpy-1.21.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:91c6f5fc58df1e0a3cc0c3a717bb3308ff850abdaa6d2d802573ee2b11f674a8"},
887
+ {file = "numpy-1.21.1-cp38-cp38-win32.whl", hash = "sha256:978010b68e17150db8765355d1ccdd450f9fc916824e8c4e35ee620590e234cd"},
888
+ {file = "numpy-1.21.1-cp38-cp38-win_amd64.whl", hash = "sha256:9749a40a5b22333467f02fe11edc98f022133ee1bfa8ab99bda5e5437b831214"},
889
+ {file = "numpy-1.21.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d7a4aeac3b94af92a9373d6e77b37691b86411f9745190d2c351f410ab3a791f"},
890
+ {file = "numpy-1.21.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d9e7912a56108aba9b31df688a4c4f5cb0d9d3787386b87d504762b6754fbb1b"},
891
+ {file = "numpy-1.21.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:25b40b98ebdd272bc3020935427a4530b7d60dfbe1ab9381a39147834e985eac"},
892
+ {file = "numpy-1.21.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:8a92c5aea763d14ba9d6475803fc7904bda7decc2a0a68153f587ad82941fec1"},
893
+ {file = "numpy-1.21.1-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:05a0f648eb28bae4bcb204e6fd14603de2908de982e761a2fc78efe0f19e96e1"},
894
+ {file = "numpy-1.21.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f01f28075a92eede918b965e86e8f0ba7b7797a95aa8d35e1cc8821f5fc3ad6a"},
895
+ {file = "numpy-1.21.1-cp39-cp39-win32.whl", hash = "sha256:88c0b89ad1cc24a5efbb99ff9ab5db0f9a86e9cc50240177a571fbe9c2860ac2"},
896
+ {file = "numpy-1.21.1-cp39-cp39-win_amd64.whl", hash = "sha256:01721eefe70544d548425a07c80be8377096a54118070b8a62476866d5208e33"},
897
+ {file = "numpy-1.21.1-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2d4d1de6e6fb3d28781c73fbde702ac97f03d79e4ffd6598b880b2d95d62ead4"},
898
+ {file = "numpy-1.21.1.zip", hash = "sha256:dff4af63638afcc57a3dfb9e4b26d434a7a602d225b42d746ea7fe2edf1342fd"},
899
+ ]
900
+ packaging = [
901
+ {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
902
+ {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
903
+ ]
904
+ pandas = [
905
+ {file = "pandas-1.1.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:bf23a3b54d128b50f4f9d4675b3c1857a688cc6731a32f931837d72effb2698d"},
906
+ {file = "pandas-1.1.5-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:5a780260afc88268a9d3ac3511d8f494fdcf637eece62fb9eb656a63d53eb7ca"},
907
+ {file = "pandas-1.1.5-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:b61080750d19a0122469ab59b087380721d6b72a4e7d962e4d7e63e0c4504814"},
908
+ {file = "pandas-1.1.5-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:0de3ddb414d30798cbf56e642d82cac30a80223ad6fe484d66c0ce01a84d6f2f"},
909
+ {file = "pandas-1.1.5-cp36-cp36m-win32.whl", hash = "sha256:70865f96bb38fec46f7ebd66d4b5cfd0aa6b842073f298d621385ae3898d28b5"},
910
+ {file = "pandas-1.1.5-cp36-cp36m-win_amd64.whl", hash = "sha256:19a2148a1d02791352e9fa637899a78e371a3516ac6da5c4edc718f60cbae648"},
911
+ {file = "pandas-1.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:26fa92d3ac743a149a31b21d6f4337b0594b6302ea5575b37af9ca9611e8981a"},
912
+ {file = "pandas-1.1.5-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:c16d59c15d946111d2716856dd5479221c9e4f2f5c7bc2d617f39d870031e086"},
913
+ {file = "pandas-1.1.5-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:3be7a7a0ca71a2640e81d9276f526bca63505850add10206d0da2e8a0a325dae"},
914
+ {file = "pandas-1.1.5-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:573fba5b05bf2c69271a32e52399c8de599e4a15ab7cec47d3b9c904125ab788"},
915
+ {file = "pandas-1.1.5-cp37-cp37m-win32.whl", hash = "sha256:21b5a2b033380adbdd36b3116faaf9a4663e375325831dac1b519a44f9e439bb"},
916
+ {file = "pandas-1.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:24c7f8d4aee71bfa6401faeba367dd654f696a77151a8a28bc2013f7ced4af98"},
917
+ {file = "pandas-1.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2860a97cbb25444ffc0088b457da0a79dc79f9c601238a3e0644312fcc14bf11"},
918
+ {file = "pandas-1.1.5-cp38-cp38-manylinux1_i686.whl", hash = "sha256:5008374ebb990dad9ed48b0f5d0038124c73748f5384cc8c46904dace27082d9"},
919
+ {file = "pandas-1.1.5-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:2c2f7c670ea4e60318e4b7e474d56447cf0c7d83b3c2a5405a0dbb2600b9c48e"},
920
+ {file = "pandas-1.1.5-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:0a643bae4283a37732ddfcecab3f62dd082996021b980f580903f4e8e01b3c5b"},
921
+ {file = "pandas-1.1.5-cp38-cp38-win32.whl", hash = "sha256:5447ea7af4005b0daf695a316a423b96374c9c73ffbd4533209c5ddc369e644b"},
922
+ {file = "pandas-1.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:4c62e94d5d49db116bef1bd5c2486723a292d79409fc9abd51adf9e05329101d"},
923
+ {file = "pandas-1.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:731568be71fba1e13cae212c362f3d2ca8932e83cb1b85e3f1b4dd77d019254a"},
924
+ {file = "pandas-1.1.5-cp39-cp39-manylinux1_i686.whl", hash = "sha256:c61c043aafb69329d0f961b19faa30b1dab709dd34c9388143fc55680059e55a"},
925
+ {file = "pandas-1.1.5-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:2b1c6cd28a0dfda75c7b5957363333f01d370936e4c6276b7b8e696dd500582a"},
926
+ {file = "pandas-1.1.5-cp39-cp39-win32.whl", hash = "sha256:c94ff2780a1fd89f190390130d6d36173ca59fcfb3fe0ff596f9a56518191ccb"},
927
+ {file = "pandas-1.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:edda9bacc3843dfbeebaf7a701763e68e741b08fccb889c003b0a52f0ee95782"},
928
+ {file = "pandas-1.1.5.tar.gz", hash = "sha256:f10fc41ee3c75a474d3bdf68d396f10782d013d7f67db99c0efbfd0acb99701b"},
929
+ ]
930
+ paramiko = [
931
+ {file = "paramiko-2.8.1-py2.py3-none-any.whl", hash = "sha256:7b5910f5815a00405af55da7abcc8a9e0d9657f57fcdd9a89894fdbba1c6b8a8"},
932
+ {file = "paramiko-2.8.1.tar.gz", hash = "sha256:85b1245054e5d7592b9088cc6d08da22445417912d3a3e48138675c7a8616438"},
933
+ ]
934
+ pillow = [
935
+ {file = "Pillow-8.4.0-cp310-cp310-macosx_10_10_universal2.whl", hash = "sha256:81f8d5c81e483a9442d72d182e1fb6dcb9723f289a57e8030811bac9ea3fef8d"},
936
+ {file = "Pillow-8.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3f97cfb1e5a392d75dd8b9fd274d205404729923840ca94ca45a0af57e13dbe6"},
937
+ {file = "Pillow-8.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb9fc393f3c61f9054e1ed26e6fe912c7321af2f41ff49d3f83d05bacf22cc78"},
938
+ {file = "Pillow-8.4.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d82cdb63100ef5eedb8391732375e6d05993b765f72cb34311fab92103314649"},
939
+ {file = "Pillow-8.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:62cc1afda735a8d109007164714e73771b499768b9bb5afcbbee9d0ff374b43f"},
940
+ {file = "Pillow-8.4.0-cp310-cp310-win32.whl", hash = "sha256:e3dacecfbeec9a33e932f00c6cd7996e62f53ad46fbe677577394aaa90ee419a"},
941
+ {file = "Pillow-8.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:620582db2a85b2df5f8a82ddeb52116560d7e5e6b055095f04ad828d1b0baa39"},
942
+ {file = "Pillow-8.4.0-cp36-cp36m-macosx_10_10_x86_64.whl", hash = "sha256:1bc723b434fbc4ab50bb68e11e93ce5fb69866ad621e3c2c9bdb0cd70e345f55"},
943
+ {file = "Pillow-8.4.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:72cbcfd54df6caf85cc35264c77ede902452d6df41166010262374155947460c"},
944
+ {file = "Pillow-8.4.0-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:70ad9e5c6cb9b8487280a02c0ad8a51581dcbbe8484ce058477692a27c151c0a"},
945
+ {file = "Pillow-8.4.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:25a49dc2e2f74e65efaa32b153527fc5ac98508d502fa46e74fa4fd678ed6645"},
946
+ {file = "Pillow-8.4.0-cp36-cp36m-win32.whl", hash = "sha256:93ce9e955cc95959df98505e4608ad98281fff037350d8c2671c9aa86bcf10a9"},
947
+ {file = "Pillow-8.4.0-cp36-cp36m-win_amd64.whl", hash = "sha256:2e4440b8f00f504ee4b53fe30f4e381aae30b0568193be305256b1462216feff"},
948
+ {file = "Pillow-8.4.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:8c803ac3c28bbc53763e6825746f05cc407b20e4a69d0122e526a582e3b5e153"},
949
+ {file = "Pillow-8.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c8a17b5d948f4ceeceb66384727dde11b240736fddeda54ca740b9b8b1556b29"},
950
+ {file = "Pillow-8.4.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1394a6ad5abc838c5cd8a92c5a07535648cdf6d09e8e2d6df916dfa9ea86ead8"},
951
+ {file = "Pillow-8.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:792e5c12376594bfcb986ebf3855aa4b7c225754e9a9521298e460e92fb4a488"},
952
+ {file = "Pillow-8.4.0-cp37-cp37m-win32.whl", hash = "sha256:d99ec152570e4196772e7a8e4ba5320d2d27bf22fdf11743dd882936ed64305b"},
953
+ {file = "Pillow-8.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:7b7017b61bbcdd7f6363aeceb881e23c46583739cb69a3ab39cb384f6ec82e5b"},
954
+ {file = "Pillow-8.4.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:d89363f02658e253dbd171f7c3716a5d340a24ee82d38aab9183f7fdf0cdca49"},
955
+ {file = "Pillow-8.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0a0956fdc5defc34462bb1c765ee88d933239f9a94bc37d132004775241a7585"},
956
+ {file = "Pillow-8.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b7bb9de00197fb4261825c15551adf7605cf14a80badf1761d61e59da347779"},
957
+ {file = "Pillow-8.4.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:72b9e656e340447f827885b8d7a15fc8c4e68d410dc2297ef6787eec0f0ea409"},
958
+ {file = "Pillow-8.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5a4532a12314149d8b4e4ad8ff09dde7427731fcfa5917ff16d0291f13609df"},
959
+ {file = "Pillow-8.4.0-cp38-cp38-win32.whl", hash = "sha256:82aafa8d5eb68c8463b6e9baeb4f19043bb31fefc03eb7b216b51e6a9981ae09"},
960
+ {file = "Pillow-8.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:066f3999cb3b070a95c3652712cffa1a748cd02d60ad7b4e485c3748a04d9d76"},
961
+ {file = "Pillow-8.4.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:5503c86916d27c2e101b7f71c2ae2cddba01a2cf55b8395b0255fd33fa4d1f1a"},
962
+ {file = "Pillow-8.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4acc0985ddf39d1bc969a9220b51d94ed51695d455c228d8ac29fcdb25810e6e"},
963
+ {file = "Pillow-8.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b052a619a8bfcf26bd8b3f48f45283f9e977890263e4571f2393ed8898d331b"},
964
+ {file = "Pillow-8.4.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:493cb4e415f44cd601fcec11c99836f707bb714ab03f5ed46ac25713baf0ff20"},
965
+ {file = "Pillow-8.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8831cb7332eda5dc89b21a7bce7ef6ad305548820595033a4b03cf3091235ed"},
966
+ {file = "Pillow-8.4.0-cp39-cp39-win32.whl", hash = "sha256:5e9ac5f66616b87d4da618a20ab0a38324dbe88d8a39b55be8964eb520021e02"},
967
+ {file = "Pillow-8.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:3eb1ce5f65908556c2d8685a8f0a6e989d887ec4057326f6c22b24e8a172c66b"},
968
+ {file = "Pillow-8.4.0-pp36-pypy36_pp73-macosx_10_10_x86_64.whl", hash = "sha256:ddc4d832a0f0b4c52fff973a0d44b6c99839a9d016fe4e6a1cb8f3eea96479c2"},
969
+ {file = "Pillow-8.4.0-pp36-pypy36_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9a3e5ddc44c14042f0844b8cf7d2cd455f6cc80fd7f5eefbe657292cf601d9ad"},
970
+ {file = "Pillow-8.4.0-pp36-pypy36_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c70e94281588ef053ae8998039610dbd71bc509e4acbc77ab59d7d2937b10698"},
971
+ {file = "Pillow-8.4.0-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:3862b7256046fcd950618ed22d1d60b842e3a40a48236a5498746f21189afbbc"},
972
+ {file = "Pillow-8.4.0-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a4901622493f88b1a29bd30ec1a2f683782e57c3c16a2dbc7f2595ba01f639df"},
973
+ {file = "Pillow-8.4.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84c471a734240653a0ec91dec0996696eea227eafe72a33bd06c92697728046b"},
974
+ {file = "Pillow-8.4.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:244cf3b97802c34c41905d22810846802a3329ddcb93ccc432870243211c79fc"},
975
+ {file = "Pillow-8.4.0.tar.gz", hash = "sha256:b8e2f83c56e141920c39464b852de3719dfbfb6e3c99a2d8da0edf4fb33176ed"},
976
+ ]
977
+ pycparser = [
978
+ {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"},
979
+ {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"},
980
+ ]
981
+ pycryptodome = [
982
+ {file = "pycryptodome-3.12.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:90ad3381ccdc6a24cc2841e295706a168f32abefe64c679695712acac71fd5da"},
983
+ {file = "pycryptodome-3.12.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e80f7469b0b3ea0f694230477d8501dc5a30a717e94fddd4821e6721f3053eae"},
984
+ {file = "pycryptodome-3.12.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:b91404611767a7485837a6f1fd20cf9a5ae0ad362040a022cd65827ecb1b0d00"},
985
+ {file = "pycryptodome-3.12.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:db66ccda65d5d20c17b00768e462a86f6f540f9aea8419a7f76cc7d9effd82cd"},
986
+ {file = "pycryptodome-3.12.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:dc88355c4b261ed259268e65705b28b44d99570337694d593f06e3b1698eaaf3"},
987
+ {file = "pycryptodome-3.12.0-cp27-cp27m-manylinux2014_aarch64.whl", hash = "sha256:6f8f5b7b53516da7511951910ab458e799173722c91fea54e2ba2f56d102e4aa"},
988
+ {file = "pycryptodome-3.12.0-cp27-cp27m-win32.whl", hash = "sha256:93acad54a72d81253242eb0a15064be559ec9d989e5173286dc21cad19f01765"},
989
+ {file = "pycryptodome-3.12.0-cp27-cp27m-win_amd64.whl", hash = "sha256:5a8c24d39d4a237dbfe181ea6593792bf9b5582c7fcfa7b8e0e12fda5eec07af"},
990
+ {file = "pycryptodome-3.12.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:32d15da81959faea6cbed95df2bb44f7f796211c110cf90b5ad3b2aeeb97fc8e"},
991
+ {file = "pycryptodome-3.12.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:aed7eb4b64c600fbc5e6d4238991ad1b4179a558401f203d1fcbd24883748982"},
992
+ {file = "pycryptodome-3.12.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:341c6bbf932c406b4f3ee2372e8589b67ac0cf4e99e7dc081440f43a3cde9f0f"},
993
+ {file = "pycryptodome-3.12.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:de0b711d673904dd6c65307ead36cb76622365a393569bf880895cba21195b7a"},
994
+ {file = "pycryptodome-3.12.0-cp27-cp27mu-manylinux2014_aarch64.whl", hash = "sha256:3558616f45d8584aee3eba27559bc6fd0ba9be6c076610ed3cc62bd5229ffdc3"},
995
+ {file = "pycryptodome-3.12.0-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:a78e4324e566b5fbc2b51e9240950d82fa9e1c7eb77acdf27f58712f65622c1d"},
996
+ {file = "pycryptodome-3.12.0-cp35-abi3-manylinux1_i686.whl", hash = "sha256:3f2f3dd596c6128d91314e60a6bcf4344610ef0e97f4ae4dd1770f86dd0748d8"},
997
+ {file = "pycryptodome-3.12.0-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:e05f994f30f1cda3cbe57441f41220d16731cf99d868bb02a8f6484c454c206b"},
998
+ {file = "pycryptodome-3.12.0-cp35-abi3-manylinux2010_i686.whl", hash = "sha256:4cded12e13785bbdf4ba1ff5fb9d261cd98162145f869e4fbc4a4b9083392f0b"},
999
+ {file = "pycryptodome-3.12.0-cp35-abi3-manylinux2010_x86_64.whl", hash = "sha256:1181c90d1a6aee68a84826825548d0db1b58d8541101f908d779d601d1690586"},
1000
+ {file = "pycryptodome-3.12.0-cp35-abi3-manylinux2014_aarch64.whl", hash = "sha256:6bb0d340c93bcb674ea8899e2f6408ec64c6c21731a59481332b4b2a8143cc60"},
1001
+ {file = "pycryptodome-3.12.0-cp35-abi3-win32.whl", hash = "sha256:39da5807aa1ff820799c928f745f89432908bf6624b9e981d2d7f9e55d91b860"},
1002
+ {file = "pycryptodome-3.12.0-cp35-abi3-win_amd64.whl", hash = "sha256:212c7f7fe11cad9275fbcff50ca977f1c6643f13560d081e7b0f70596df447b8"},
1003
+ {file = "pycryptodome-3.12.0-pp27-pypy_73-macosx_10_9_x86_64.whl", hash = "sha256:b07a4238465eb8c65dd5df2ab8ba6df127e412293c0ed7656c003336f557a100"},
1004
+ {file = "pycryptodome-3.12.0-pp27-pypy_73-manylinux1_x86_64.whl", hash = "sha256:a6e1bcd9d5855f1a3c0f8d585f44c81b08f39a02754007f374fb8db9605ba29c"},
1005
+ {file = "pycryptodome-3.12.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:aceb1d217c3a025fb963849071446cf3aca1353282fe1c3cb7bd7339a4d47947"},
1006
+ {file = "pycryptodome-3.12.0-pp27-pypy_73-win32.whl", hash = "sha256:f699360ae285fcae9c8f53ca6acf33796025a82bb0ccd7c1c551b04c1726def3"},
1007
+ {file = "pycryptodome-3.12.0-pp36-pypy36_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d845c587ceb82ac7cbac7d0bf8c62a1a0fe7190b028b322da5ca65f6e5a18b9e"},
1008
+ {file = "pycryptodome-3.12.0-pp36-pypy36_pp73-manylinux1_x86_64.whl", hash = "sha256:d8083de50f6dec56c3c6f270fb193590999583a1b27c9c75bc0b5cac22d438cc"},
1009
+ {file = "pycryptodome-3.12.0-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:9ea2f6674c803602a7c0437fccdc2ea036707e60456974fe26ca263bd501ec45"},
1010
+ {file = "pycryptodome-3.12.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:5d4264039a2087977f50072aaff2346d1c1c101cb359f9444cf92e3d1f42b4cd"},
1011
+ {file = "pycryptodome-3.12.0.zip", hash = "sha256:12c7343aec5a3b3df5c47265281b12b611f26ec9367b6129199d67da54b768c1"},
1012
+ ]
1013
+ pydub = [
1014
+ {file = "pydub-0.25.1-py2.py3-none-any.whl", hash = "sha256:65617e33033874b59d87db603aa1ed450633288aefead953b30bded59cb599a6"},
1015
+ {file = "pydub-0.25.1.tar.gz", hash = "sha256:980a33ce9949cab2a569606b65674d748ecbca4f0796887fd6f46173a7b0d30f"},
1016
+ ]
1017
+ pynacl = [
1018
+ {file = "PyNaCl-1.4.0-cp27-cp27m-macosx_10_10_x86_64.whl", hash = "sha256:ea6841bc3a76fa4942ce00f3bda7d436fda21e2d91602b9e21b7ca9ecab8f3ff"},
1019
+ {file = "PyNaCl-1.4.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:d452a6746f0a7e11121e64625109bc4468fc3100452817001dbe018bb8b08514"},
1020
+ {file = "PyNaCl-1.4.0-cp27-cp27m-win32.whl", hash = "sha256:2fe0fc5a2480361dcaf4e6e7cea00e078fcda07ba45f811b167e3f99e8cff574"},
1021
+ {file = "PyNaCl-1.4.0-cp27-cp27m-win_amd64.whl", hash = "sha256:f8851ab9041756003119368c1e6cd0b9c631f46d686b3904b18c0139f4419f80"},
1022
+ {file = "PyNaCl-1.4.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:7757ae33dae81c300487591c68790dfb5145c7d03324000433d9a2c141f82af7"},
1023
+ {file = "PyNaCl-1.4.0-cp35-abi3-macosx_10_10_x86_64.whl", hash = "sha256:757250ddb3bff1eecd7e41e65f7f833a8405fede0194319f87899690624f2122"},
1024
+ {file = "PyNaCl-1.4.0-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:30f9b96db44e09b3304f9ea95079b1b7316b2b4f3744fe3aaecccd95d547063d"},
1025
+ {file = "PyNaCl-1.4.0-cp35-abi3-win32.whl", hash = "sha256:4e10569f8cbed81cb7526ae137049759d2a8d57726d52c1a000a3ce366779634"},
1026
+ {file = "PyNaCl-1.4.0-cp35-abi3-win_amd64.whl", hash = "sha256:c914f78da4953b33d4685e3cdc7ce63401247a21425c16a39760e282075ac4a6"},
1027
+ {file = "PyNaCl-1.4.0-cp35-cp35m-win32.whl", hash = "sha256:06cbb4d9b2c4bd3c8dc0d267416aaed79906e7b33f114ddbf0911969794b1cc4"},
1028
+ {file = "PyNaCl-1.4.0-cp35-cp35m-win_amd64.whl", hash = "sha256:511d269ee845037b95c9781aa702f90ccc36036f95d0f31373a6a79bd8242e25"},
1029
+ {file = "PyNaCl-1.4.0-cp36-cp36m-win32.whl", hash = "sha256:11335f09060af52c97137d4ac54285bcb7df0cef29014a1a4efe64ac065434c4"},
1030
+ {file = "PyNaCl-1.4.0-cp36-cp36m-win_amd64.whl", hash = "sha256:cd401ccbc2a249a47a3a1724c2918fcd04be1f7b54eb2a5a71ff915db0ac51c6"},
1031
+ {file = "PyNaCl-1.4.0-cp37-cp37m-win32.whl", hash = "sha256:8122ba5f2a2169ca5da936b2e5a511740ffb73979381b4229d9188f6dcb22f1f"},
1032
+ {file = "PyNaCl-1.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:537a7ccbea22905a0ab36ea58577b39d1fa9b1884869d173b5cf111f006f689f"},
1033
+ {file = "PyNaCl-1.4.0-cp38-cp38-win32.whl", hash = "sha256:9c4a7ea4fb81536c1b1f5cc44d54a296f96ae78c1ebd2311bd0b60be45a48d96"},
1034
+ {file = "PyNaCl-1.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:7c6092102219f59ff29788860ccb021e80fffd953920c4a8653889c029b2d420"},
1035
+ {file = "PyNaCl-1.4.0.tar.gz", hash = "sha256:54e9a2c849c742006516ad56a88f5c74bf2ce92c9f67435187c3c5953b346505"},
1036
+ ]
1037
+ pyparsing = [
1038
+ {file = "pyparsing-3.0.6-py3-none-any.whl", hash = "sha256:04ff808a5b90911829c55c4e26f75fa5ca8a2f5f36aa3a51f68e27033341d3e4"},
1039
+ {file = "pyparsing-3.0.6.tar.gz", hash = "sha256:d9bdec0013ef1eb5a84ab39a3b3868911598afa494f5faa038647101504e2b81"},
1040
+ ]
1041
+ python-dateutil = [
1042
+ {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"},
1043
+ {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"},
1044
+ ]
1045
+ pytz = [
1046
+ {file = "pytz-2021.3-py2.py3-none-any.whl", hash = "sha256:3672058bc3453457b622aab7a1c3bfd5ab0bdae451512f6cf25f64ed37f5b87c"},
1047
+ {file = "pytz-2021.3.tar.gz", hash = "sha256:acad2d8b20a1af07d4e4c9d2e9285c5ed9104354062f275f3fcd88dcef4f1326"},
1048
+ ]
1049
+ requests = [
1050
+ {file = "requests-2.26.0-py2.py3-none-any.whl", hash = "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24"},
1051
+ {file = "requests-2.26.0.tar.gz", hash = "sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7"},
1052
+ ]
1053
+ setuptools-scm = [
1054
+ {file = "setuptools_scm-6.3.2-py3-none-any.whl", hash = "sha256:4c64444b1d49c4063ae60bfe1680f611c8b13833d556fd1d6050c0023162a119"},
1055
+ {file = "setuptools_scm-6.3.2.tar.gz", hash = "sha256:a49aa8081eeb3514eb9728fa5040f2eaa962d6c6f4ec9c32f6c1fba88f88a0f2"},
1056
+ ]
1057
+ six = [
1058
+ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
1059
+ {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
1060
+ ]
1061
+ tomli = [
1062
+ {file = "tomli-2.0.0-py3-none-any.whl", hash = "sha256:b5bde28da1fed24b9bd1d4d2b8cba62300bfb4ec9a6187a957e8ddb9434c5224"},
1063
+ {file = "tomli-2.0.0.tar.gz", hash = "sha256:c292c34f58502a1eb2bbb9f5bbc9a5ebc37bee10ffb8c2d6bbdfa8eb13cc14e1"},
1064
+ ]
1065
+ typing-extensions = [
1066
+ {file = "typing_extensions-4.0.1-py3-none-any.whl", hash = "sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b"},
1067
+ {file = "typing_extensions-4.0.1.tar.gz", hash = "sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e"},
1068
+ ]
1069
+ urllib3 = [
1070
+ {file = "urllib3-1.26.7-py2.py3-none-any.whl", hash = "sha256:c4fdf4019605b6e5423637e01bc9fe4daef873709a7973e195ceba0a62bbc844"},
1071
+ {file = "urllib3-1.26.7.tar.gz", hash = "sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece"},
1072
+ ]
1073
+ werkzeug = [
1074
+ {file = "Werkzeug-2.0.2-py3-none-any.whl", hash = "sha256:63d3dc1cf60e7b7e35e97fa9861f7397283b75d765afcaefd993d6046899de8f"},
1075
+ {file = "Werkzeug-2.0.2.tar.gz", hash = "sha256:aa2bb6fc8dee8d6c504c0ac1e7f5f7dc5810a9903e793b6f715a9f015bdadb9a"},
1076
+ ]
1077
+ zipp = [
1078
+ {file = "zipp-3.6.0-py3-none-any.whl", hash = "sha256:9fe5ea21568a0a70e50f273397638d39b03353731e6cbbb3fd8502a33fec40bc"},
1079
+ {file = "zipp-3.6.0.tar.gz", hash = "sha256:71c644c5369f4a6e07636f0aa966270449561fcea2e3d6747b8d23efaa9d7832"},
1080
+ ]
pyproject.toml ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [tool.poetry]
2
+ name = "radiobee-aligner"
3
+ version = "0.1.0"
4
+ description = ""
5
+ authors = ["ffreemt"]
6
+
7
+ [tool.poetry.dependencies]
8
+ python = "^3.7"
9
+ gradio = "*"
10
+
11
+ [tool.poetry.dev-dependencies]
12
+
13
+ [build-system]
14
+ requires = ["poetry-core>=1.0.0"]
15
+ build-backend = "poetry.core.masonry.api"
pyrightconfig.json ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "include": ["tests", "radiobee"],
3
+ "venvPath": ".venv",
4
+ "reportTypeshedErrors": false,
5
+ "reportMissingImports": true,
6
+ "reportMissingTypeStubs": false,
7
+ "pythonVersion": "3.8",
8
+ "ignore": []
9
+ }
radiobee/__init__.py CHANGED
@@ -1 +1 @@
1
- """Init."""
1
+ """Init."""
radiobee/__main__.py CHANGED
@@ -1,10 +1,346 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import gradio as gr
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
  def greet(input):
4
  """Greet yo."""
5
  return f"'Sup yo! (your input: {input})"
6
 
7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  if __name__ == "__main__":
9
- iface = gr.Interface(fn=greet, inputs="text", outputs="text")
10
- iface.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Run interactively."""
2
+ from typing import Tuple, Optional
3
+
4
+ import joblib
5
+ from random import randint
6
+ from textwrap import dedent
7
+ from itertools import zip_longest
8
+ from sklearn.cluster import DBSCAN
9
+
10
+ from socket import socket, AF_INET, SOCK_STREAM
11
+ import signal
12
+ from varname import nameof
13
+ from logzero import logger
14
+
15
+ import numpy as np
16
+ import pandas as pd
17
+ import seaborn as sns
18
+ import matplotlib.pyplot as plt
19
+
20
+ # from tabulate import tabulate
21
+ from fastlid import fastlid
22
+
23
  import gradio as gr
24
+ from radiobee.process_upload import process_upload
25
+ from radiobee.files2df import files2df
26
+ from radiobee.file2text import file2text
27
+ from radiobee.lists2cmat import lists2cmat
28
+ from radiobee.plot_df import plot_df
29
+ from radiobee.cmat2tset import cmat2tset
30
+
31
+ sns.set()
32
+ sns.set_style("darkgrid")
33
+ fastlid.set_languages = ["en", "zh"]
34
+
35
+ signal.signal(signal.SIGINT, signal.SIG_DFL)
36
+ print("Press Ctrl+C to quit\n")
37
+
38
+ def savelzma(obj, fileloc: str = None):
39
+ if fileloc is None:
40
+ fileloc = nameof(obj) # this wont work
41
+ joblib.dump(obj, f"data/{fileloc}.lzma")
42
+
43
 
44
  def greet(input):
45
  """Greet yo."""
46
  return f"'Sup yo! (your input: {input})"
47
 
48
 
49
+ def upfile1(file1, file2=None) -> Tuple[str, str]:
50
+ """Upload file1, file2."""
51
+ return file1.name, f"'Sup yo! (your input: {input})"
52
+
53
+ def process_2upoads(file1, file2):
54
+ """Process stuff."""
55
+ # return f"{process_upload(file1)}\n===***\n{process_upload(file2)}"
56
+
57
+ text1 = [_.strip() for _ in process_upload(file1).splitlines() if _.strip()]
58
+ text2 = [_.strip() for _ in process_upload(file2).splitlines() if _.strip()]
59
+
60
+ text1, text2 = zip(*zip_longest(text1, text2, fillvalue=""))
61
+
62
+ df = pd.DataFrame({"text1": text1, "text2": text2})
63
+
64
+ # return tabulate(df)
65
+ # return tabulate(df, tablefmt="grid")
66
+ # return tabulate(df, tablefmt='html')
67
+
68
+ return df
69
+
70
+
71
  if __name__ == "__main__":
72
+ _ = """
73
+ fn = process_2upoads
74
+ inputs = ["file", "file"]
75
+ examples = [
76
+ ["data/test_zh.txt", "data/test_en.txt"],
77
+ ["data/test_en.txt", "data/test_zh.txt"],
78
+ ]
79
+ outputs = ["dataframe"]
80
+ # """
81
+ import logzero
82
+ logzero.loglevel(10)
83
+ logger.debug(" debug ")
84
+ logger.info(" info ")
85
+
86
+ # _ = """
87
+ inputs = [
88
+ gr.inputs.Textbox(
89
+ # placeholder="Input something here",
90
+ default="test text")
91
+ ]
92
+ inputs = ["file", "file"]
93
+ inputs = [
94
+ gr.inputs.File(label="file 1"),
95
+ # gr.inputs.File(file_count="multiple", label="file 2", optional=True),
96
+ gr.inputs.File(label="file 2", optional=True),
97
+ ]
98
+ examples = [
99
+ ["data/test_zh.txt", "data/test_en.txt"],
100
+ ["data/test_en.txt", "data/test_zh.txt"],
101
+ ["data/shakespeare_zh500.txt", "data/shakespeare_en500.txt"],
102
+ ["data/shakespeare_en500.txt", "data/shakespeare_zh500.txt"],
103
+ ]
104
+ outputs = ["dataframe", "plot"]
105
+ outputs = ["plot"]
106
+ outputs = ["dataframe", "plot"]
107
+ out1 = gr.outputs.Dataframe(
108
+ headers=None,
109
+ max_rows=12, # 20
110
+ max_cols=None,
111
+ overflow_row_behaviour='paginate',
112
+ type='auto',
113
+ label="To be aligned",
114
+ )
115
+ outputs = [
116
+ out1,
117
+ "plot",
118
+ ]
119
+ # outputs = ["dataframe", "plot", "plot"] # wont work
120
+ # outputs = ["dataframe"]
121
+ # outputs = ["dataframe", "dataframe", ]
122
+
123
+ def fn(file1, file2):
124
+ """Process inputs."""
125
+ logger.debug(" *debug* ")
126
+
127
+ # logger.info("file1: *%s*, file2: *%s*", file1, file2)
128
+ logger.info("file1.name: *%s*, file2.name: *%s*", file1.name, file2.name)
129
+
130
+ # bypass if file1 or file2 is str input
131
+ if not (isinstance(file1, str) or isinstance(file2, str)):
132
+ text1 = file2text(file1)
133
+ text2 = file2text(file2)
134
+ lang1, _ = fastlid(text1)
135
+ lang2, _ = fastlid(text2)
136
+
137
+ df1 = files2df(file1, file2)
138
+
139
+ lst1 = [elm for elm in df1.text1 if elm]
140
+ lst2 = [elm for elm in df1.text2 if elm]
141
+ len1 = len(lst1)
142
+ len2 = len(lst2)
143
+
144
+ # this wont work
145
+ # for obj in [text1, text2, df1, lst1, lst2, ]:
146
+ # savelzma(text1) wont work
147
+ joblib.dump(text1, f"data/{nameof(text1)}.lzma")
148
+ joblib.dump(text2, f"data/{nameof(text2)}.lzma")
149
+ joblib.dump(df1, f"data/{nameof(df1)}.lzma")
150
+ joblib.dump(lst1, f"data/{nameof(lst1)}.lzma")
151
+ joblib.dump(lst2, f"data/{nameof(lst2)}.lzma")
152
+
153
+ cmat = lists2cmat(lst1, lst2)
154
+
155
+ tset = pd.DataFrame(cmat2tset(cmat))
156
+ tset.columns = ["x", "y", "cos"]
157
+
158
+ print("lst1: %s" % lst1)
159
+ print("lst2: %s" % lst2)
160
+ print("cmat: %s" % cmat)
161
+ print("tset: %s" % tset)
162
+
163
+ logger.debug("lst1: %s", lst1)
164
+ logger.debug("lst2: %s", lst2)
165
+ logger.debug("cmat: %s", cmat)
166
+ logger.debug("tset: %s", tset)
167
+
168
+
169
+ # plt0 = plot_df(pd.DataFrame(cmat))
170
+ df_ = tset
171
+ min_samples: int = 6
172
+ eps: float = 10
173
+ ylim: Optional[int] = None
174
+ xlabel: str = lang1
175
+ ylabel: str = lang2
176
+
177
+ sns.set()
178
+ sns.set_style("darkgrid")
179
+
180
+ # fig, (ax0, ax1) = plt.subplots(1, 2, figsize=(11.69, 8.27))
181
+ fig, ([ax2, ax0], [ax1, ax3]) = plt.subplots(2, 2, figsize=(11.69, 8.27))
182
+ # plt.subplot_tool()
183
+ fig.subplots_adjust(hspace=.4)
184
+
185
+ sns.heatmap(cmat, cmap="viridis_r", ax=ax2).invert_yaxis()
186
+ ax2.set_xlabel(xlabel)
187
+ ax2.set_ylabel(ylabel)
188
+ ax2.set_title("cos similarity heatmap")
189
+
190
+ fig.suptitle("alignment projection")
191
+
192
+ _ = DBSCAN(min_samples=min_samples, eps=eps).fit(df_).labels_ > -1
193
+ _x = DBSCAN(min_samples=min_samples, eps=eps).fit(df_).labels_ < 0
194
+
195
+ df_.plot.scatter("x", "y", c="cos", cmap="viridis_r", ax=ax0)
196
+
197
+ # clustered
198
+ df_[_].plot.scatter("x", "y", c="cos", cmap="viridis_r", ax=ax1)
199
+
200
+ # outliers
201
+ df_[_x].plot.scatter("x", "y", c="r", marker="x", alpha=0.6, ax=ax0)
202
+
203
+ # ax0.set_xlabel("")
204
+ # ax0.set_ylabel("zh")
205
+ ax0.set_xlabel(xlabel)
206
+ ax0.set_ylabel(ylabel)
207
+
208
+ ax0.set_xlim(0, len1)
209
+ ax0.set_ylim(0, len2)
210
+ ax0.set_title("max similarity along columns ('x': outliers)")
211
+
212
+ # ax1.set_xlabel("en")
213
+ # ax1.set_ylabel("zh")
214
+ ax1.set_xlabel(xlabel)
215
+ ax1.set_ylabel(ylabel)
216
+
217
+ ax1.set_xlim(0, len1)
218
+ ax1.set_ylim(0, len2)
219
+ ax1.set_title(f"potential aligned pairs ({round(sum(_) / len1, 2):.0%})")
220
+
221
+ # return df, plot_df(pd.DataFrame(cmat))
222
+ # tset.plot.scatter("x", "y", c="cos", cmap="viridis_r")
223
+ else:
224
+ fig, ax1 = plt.subplots()
225
+ df1 = pd.DataFrame(
226
+ [[5.1, 3.5, 0],
227
+ [4.9, 3.0, 0],
228
+ [7.0, 3.2, 1],
229
+ [6.4, 3.2, 1],
230
+ [5.9, 3.0, 2]],
231
+ columns=['length', 'width', 'species']
232
+ )
233
+ df1.plot.scatter(x='length', y='width', c='DarkBlue', ax=ax1)
234
+ # plt_heatmap = plt
235
+
236
+ # plt.scatter(df.length, df.width) # gradio eturn plt.gcf() or plt
237
+
238
+ # return df, plt
239
+ # return plt
240
+ # return df, df
241
+ # return df1.iloc[:10, :], plt
242
+
243
+ # pd.concat([df0, pd.DataFrame([[".", ".", "..."]], columns=df0.columns)], ignore_index=1)
244
+ # pd.concat([df0.iloc[:2, :], pd.DataFrame([[".", ".", "..."]], columns=df0.columns), df0.iloc[-1:, :]], ignore_index=1)
245
+
246
+ # _ = pd.concat([df1.iloc[:4, :], pd.DataFrame([["...", "...", "...", ]], columns=df1.columns), df1.iloc[-2:, :]], ignore_index=True)
247
+ # _ = pd.concat([df.iloc[:2, :], pd.DataFrame([[".", ".", "..."]], columns=df.columns), df.iloc[-1:, :]], ignore_index=1)
248
+
249
+ _ = pd.concat([df1.iloc[:4, :], pd.DataFrame([["...", "...", ]], columns=df1.columns), df1.iloc[-4:, :]], ignore_index=1)
250
+
251
+ return _, plt
252
+ # return _, plt
253
+
254
+ # """
255
+
256
+ server_port = 7860
257
+ with socket(AF_INET, SOCK_STREAM) as sock:
258
+ sock.settimeout(0.01) # 10ms
259
+
260
+ # try numb times before giving up
261
+ numb = 5
262
+ for _ in range(numb):
263
+ if sock.connect_ex(("127.0.0.1", server_port)) != 0: # port idle
264
+ break
265
+ server_port = server_port + randint(0, 50)
266
+ else:
267
+ raise SystemExit(
268
+ f"Tried {numb} times to no avail, giving up..."
269
+ )
270
+
271
+ article = dedent("""
272
+ Click "Clear" first for subsequent submits
273
+ """)
274
+ css = ".output_image, .input_image {height: 40rem !important; width: 100% !important;}"
275
+ css_file = ".input_file, .output_file {height: 9rem !important; width: 100% !important;}"
276
+
277
+ logger.info("running at port %s", server_port)
278
+
279
+ iface = gr.Interface(
280
+ # fn=greet,
281
+ # inputs="text",
282
+ # fn=process_upload,
283
+ # fn=process_2upoads,
284
+ # inputs=["file", "file"],
285
+ # outputs="text",
286
+ # outputs="html",
287
+ fn=fn,
288
+ inputs=inputs,
289
+ outputs=outputs,
290
+ title="radiobee-aligner🔠",
291
+ description="showcasing a blazing fast dualtext aligner, currrently supported language pairs: en-zh/zh-en",
292
+ article=article,
293
+ examples=examples,
294
+ # theme="darkgrass",
295
+ layout="vertical", # horizontal unaligned
296
+ height=150, # 500
297
+ width=900, # 900
298
+ allow_flagging=False,
299
+ flagging_options=["fatal", "bug", "brainstorm", "excelsior", "paragon"],
300
+ css=f"{css} {css_file}",
301
+ )
302
+
303
+ iface.launch(
304
+ # share=False,
305
+ share=True,
306
+ debug=True,
307
+ server_name="0.0.0.0",
308
+ server_port=server_port,
309
+ # show_tips=True,
310
+ enable_queue=True,
311
+ )
312
+
313
+ _ = """
314
+
315
+ ax = sns.heatmap(cmat, cmap="viridis_r")
316
+
317
+ ax.invert_yaxis()
318
+ ax.set_xlabel(fastlid(df.text1)[0])
319
+ ax.set_xlabel(fastlid(df.text2)[0])
320
+
321
+ # return df, plt
322
+ return plt.gca()
323
+
324
+ https://colab.research.google.com/drive/1Gz9624VeAQLT7wlETgjOjPVURzQckXI0#scrollTo=qibtTvwecgsL colab gradio-file-inputs-upload.ipynb
325
+ iface = gr.Interface(plot_text, "file", "image")
326
+
327
+ def is_port_in_use(port):
328
+ import socket
329
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
330
+ return s.connect_ex(('localhost', port)) == 0
331
+
332
+ socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect_ex(('127.0.0.1', 7911))
333
+
334
+ ---
335
+ css https://huggingface.co/spaces/nielsr/LayoutLMv2-FUNSD/blob/main/app.py#L83
336
+
337
+ css = ".output_image, .input_image {height: 40rem !important; width: 100% !important;}"
338
+ #css = "@media screen and (max-width: 600px) { .output_image, .input_image {height:20rem !important; width: 100% !important;} }"
339
+ # css = ".output_image, .input_image {height: 600px !important}"
340
+
341
+ mod = 'en2zh'
342
+ packname = packx.__name__
343
+
344
+ globals()[mod] = getattr(importlib.import_module(f"{packname}.{mod}"), mod)
345
+
346
+ """
radiobee/app.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Talk to spaces VM via subprocess.check_output."""
2
+ # import httpx
3
+ import subprocess as sp
4
+ from shlex import split
5
+ import gradio as gr
6
+
7
+
8
+ def greet(command):
9
+ """Probe vm."""
10
+ try:
11
+ out = sp.check_output(split(command), encoding="utf8")
12
+ except Exception as e:
13
+ out = str(e)
14
+ # return "Hello " + name + "!!"
15
+ if not (out and out.strip()):
16
+ out = "No output, that's all we know."
17
+ return out
18
+
19
+
20
+ iface = gr.Interface(
21
+ fn=greet,
22
+ inputs="text",
23
+ outputs="text",
24
+ examples=[
25
+ "cat /proc/version",
26
+ "free # show free memory",
27
+ "uname -m",
28
+ "df -h .",
29
+ "cat /proc/cpuinfo",
30
+ ],
31
+ title="probe the system",
32
+ description="talk to the system via subprocess.check_output ",
33
+ )
34
+
35
+ # iface.launch(share=True, debug=True)
36
+ iface.launch(debug=True)
radiobee/cmat2tset.py ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Gen triple-set from a matrix."""
2
+ from typing import List, Tuple, Union
3
+
4
+ import numpy as np
5
+ import pandas as pd
6
+
7
+
8
+ # fmt: off
9
+ def cmat2tset(
10
+ cmat1: Union[List[List[float]], np.ndarray, pd.DataFrame],
11
+ # thirdcol: bool = True
12
+ ) -> np.ndarray:
13
+ # ) -> List[Union[Tuple[int, int], Tuple[int, int, float]]]:
14
+ # fmt: on
15
+ """Gen triple-set from a matrix.
16
+
17
+ Args
18
+ cmat: 2d-array or list, correlation or other metric matrix
19
+ # thirdcol: bool, whether to output a third column (max value)
20
+
21
+ Returns
22
+ Obtain the max and argmax for each column, erase the row afterwards to eliminate one single row that would dominate
23
+ every column.
24
+ """
25
+ # if isinstance(cmat, list):
26
+ cmat = np.array(cmat1)
27
+
28
+ if not np.prod(cmat.shape):
29
+ raise SystemError("data not 2d...")
30
+
31
+ _ = """
32
+ # y00 = range(cmat.shape[1]) # cmat.shape[0] long time wasting bug
33
+
34
+ yargmax = cmat.argmax(axis=0)
35
+ if thirdcol:
36
+ ymax = cmat.max(axis=0)
37
+
38
+ res = [*zip(y00, yargmax, ymax)] # type: ignore
39
+ # to unzip
40
+ # a, b, c = zip(*res)
41
+
42
+ return res
43
+
44
+ _ = [*zip(y00, yargmax)] # type: ignore
45
+ return _
46
+ """
47
+ low_ = cmat.min() - 1
48
+ argmax_max = []
49
+ src_len, tgt_len = cmat.shape
50
+ for _ in range(min(src_len, tgt_len)):
51
+ argmax = int(cmat.argmax())
52
+ row, col = divmod(argmax, tgt_len)
53
+ argmax_max.append([col, row, cmat.max()])
54
+
55
+ # erase row-th row and col-th col of cmat
56
+ cmat[row, :] = low_
57
+ cmat[:, col] = low_
58
+
59
+ return np.array(argmax_max)
radiobee/docterm_scores.py ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Generate a doc-term score matrix based on textacy.representation.Vectorizer.
2
+
3
+ refer also to fast-scores fast_scores.py and gen_model.py (sklearn.feature_extraction.text.TfidfVectorizer).
4
+ """
5
+ from typing import Dict, Iterable, List, Optional, Union
6
+ import numpy as np
7
+ from itertools import chain
8
+ from psutil import virtual_memory
9
+ from more_itertools import ilen
10
+
11
+ from textacy.representations import Vectorizer
12
+ from logzero import logger
13
+
14
+ from radiobee.gen_model import gen_model
15
+
16
+
17
+ # fmt: off
18
+ def docterm_scores(
19
+ doc1: Iterable[Iterable[str]], # List[List[str]],
20
+ doc2: Iterable[Iterable[str]],
21
+ model: Vectorizer = None,
22
+ tf_type: str = 'linear',
23
+ idf_type: Optional[str] = "smooth",
24
+ # dl_type: Optional[str] = "sqrt", # "lucene-style tfidf"
25
+ dl_type: Optional[str] = None, #
26
+ norm: Optional[str] = "l2", # + "l2"
27
+ min_df: Union[int, float] = 1,
28
+ max_df: Union[int, float] = 1.0,
29
+ max_n_terms: Optional[int] = None,
30
+ vocabulary_terms: Optional[Union[Dict[str, int], Iterable[str]]] = None
31
+ ) -> np.ndarray:
32
+ # fmt: on
33
+ """Generate a doc-term score matrix based on textacy.representation.Vectorizer.
34
+
35
+ Args
36
+ doc1: tokenized doc of n1
37
+ doc2: tokenized doc of n2
38
+ model: if None, generate one ad hoc from doc1 and doc2 ("lucene-style tfidf").
39
+ rest: refer to textacy.representation.Vectorizer
40
+ Attributes
41
+ vectorizer
42
+
43
+ Returns
44
+ n1 x n2 similarity matrix of float numbers
45
+ """
46
+ # make sure doc1/doc2 is of the right typing
47
+ try:
48
+ for xelm in iter(doc1):
49
+ for elm in iter(xelm):
50
+ assert isinstance(elm, str)
51
+ except AssertionError:
52
+ raise AssertionError(" doc1 is not of the typing Iterable[Iterable[str]] ")
53
+ except Exception as e:
54
+ logger.error(e)
55
+ raise
56
+ try:
57
+ for xelm in iter(doc2):
58
+ for elm in iter(xelm):
59
+ assert isinstance(elm, str)
60
+ except AssertionError:
61
+ raise AssertionError(" doc2 is not of the typing Iterable[Iterable[str]] ")
62
+ except Exception as e:
63
+ logger.error(e)
64
+ raise
65
+
66
+ if model is None:
67
+ model = gen_model(
68
+ [*chain(doc1, doc2)],
69
+ tf_type=tf_type,
70
+ idf_type=idf_type,
71
+ dl_type=dl_type,
72
+ norm=norm,
73
+ min_df=min_df,
74
+ max_df=max_df,
75
+ max_n_terms=max_n_terms,
76
+ vocabulary_terms=vocabulary_terms
77
+ )
78
+ docterm_scores.model = model
79
+
80
+ # a1 = dt.toarray(), a2 = doc_term_matrix.toarray()
81
+ # np.all(np.isclose(a1, a2))
82
+
83
+ dt1 = model.transform(doc1)
84
+ dt2 = model.transform(doc2)
85
+
86
+ # virtual_memory().available / 8: 64bits float
87
+ require_ram = ilen(iter(doc1)) * ilen(iter(doc2)) * 8
88
+ if require_ram > virtual_memory().available:
89
+ logger.warning("virtual_memory().available: %s", virtual_memory().available)
90
+ logger.warning("memory required: %s", require_ram)
91
+
92
+ if require_ram > virtual_memory().available * 10:
93
+ logger.warning("You'll likely encounter memory problem, such as slow down response and/or OOM.")
94
+
95
+ # return dt1.doc(dt2.T)
96
+ return dt2.toarray().dot(dt1.toarray().T)
radiobee/en2zh.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Translate english to chinese via a dict."""
2
+ # from typing import List, Union
3
+ from typing import Iterable, List, Union
4
+
5
+ import warnings
6
+
7
+ import copy
8
+ from radiobee.mdx_e2c import mdx_e2c
9
+
10
+ warnings.simplefilter('ignore', DeprecationWarning)
11
+
12
+
13
+ # fmt: off
14
+ def en2zh(
15
+ # text: Union[str, List[List[str]]],
16
+ # text: Union[str, List[str]],
17
+ text: Union[str, Iterable[str]],
18
+ ) -> List[str]:
19
+ # fmt: on
20
+ """Translate english to chinese via a dict.
21
+
22
+ Args
23
+ text: to translate, list of str
24
+
25
+ Returns
26
+ res: list of str
27
+ """
28
+ res = copy.deepcopy(text)
29
+ if isinstance(text, str):
30
+ # res = [text.split()]
31
+ res = [text]
32
+
33
+ # if res and isinstance(res[0], str):
34
+ # res = [line.lower().split() for line in res]
35
+
36
+ # res = ["".join([word_tr(word) for word in line]) for line in res]
37
+ _ = []
38
+ for line in res:
39
+ line_tr = [mdx_e2c(word) for word in line.split()]
40
+ _.append("".join(line_tr))
41
+
42
+ return _
radiobee/file2text.py ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Convert file to text."""
2
+ from radiobee.process_upload import process_upload
3
+
4
+
5
+ def file2text(file1):
6
+ """Convert file to text."""
7
+ try:
8
+ filename1 = file1.name
9
+ except AttributeError:
10
+ filename1 = ""
11
+ if filename1:
12
+ text1 = process_upload(file1)
13
+ else:
14
+ text1 = ""
15
+ return text1
radiobee/files2df.py ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Convert two iesl to pandas.DataFrame."""
2
+ from itertools import zip_longest
3
+ import tempfile
4
+ import pandas as pd
5
+ from radiobee.process_upload import process_upload
6
+
7
+
8
+ def files2df(file1, file2):
9
+ """Convert two files to pd.DataFrame."""
10
+ text1 = [_.strip() for _ in process_upload(file1).splitlines() if _.strip()]
11
+
12
+ # if file2 is tempfile._TemporaryFileWrapper:
13
+ try:
14
+ filename = file2.name
15
+ except AttributeError:
16
+ filename = ""
17
+ if filename:
18
+ text2 = [_.strip() for _ in process_upload(file2).splitlines() if _.strip()]
19
+ else:
20
+ text2 = [""]
21
+
22
+ text1, text2 = zip(*zip_longest(text1, text2, fillvalue=""))
23
+
24
+ df = pd.DataFrame({"text1": text1, "text2": text2})
25
+
26
+ return df
27
+
28
+ _ = """
29
+ # return tabulate(df)
30
+ # return tabulate(df, tablefmt="grid")
31
+ # return tabulate(df, tablefmt='html')
32
+ # """
radiobee/gen_model.py ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Generate a model (textacy.representations.Vectorizer).
2
+
3
+ vectorizer = Vectorizer(
4
+ tf_type="linear", idf_type="smooth", norm="l2",
5
+ min_df=3, max_df=0.95)
6
+ doc_term_matrix = vectorizer.fit_transform(tokenized_docs)
7
+ doc_term_matrix
8
+
9
+ tokenized_docs = [insert_spaces(elm).split() for elm in textzh]
10
+ """
11
+ from typing import Dict, Iterable, List, Optional, Union
12
+
13
+ from textacy.representations import Vectorizer
14
+ from logzero import logger
15
+
16
+
17
+ # fmt: off
18
+ def gen_model(
19
+ tokenized_docs: Iterable[Iterable[str]], # List[List[str]],
20
+ tf_type: str = 'linear',
21
+ idf_type: Optional[str] = "smooth",
22
+ dl_type: str = None, # Optional[str] = "sqrt" “lucene-style tfidf”
23
+ norm: Optional[str] = "l2", # + "l2"
24
+ min_df: Union[int, float] = 1,
25
+ max_df: Union[int, float] = 1.0,
26
+ max_n_terms: Optional[int] = None,
27
+ vocabulary_terms: Optional[Union[Dict[str, int], Iterable[str]]] = None
28
+ ) -> Vectorizer:
29
+ # fmt: on
30
+ """Generate a model (textacy.representations.Vectorizer).
31
+
32
+ Args:
33
+ doc: tokenized docs
34
+
35
+ (refer to textacy.representation.Vectorizer)
36
+ tf_type: Type of term frequency (tf) to use for weights' local component:
37
+
38
+ - "linear": tf (tfs are already linear, so left as-is)
39
+ - "sqrt": tf => sqrt(tf)
40
+ - "log": tf => log(tf) + 1
41
+ - "binary": tf => 1
42
+
43
+ idf_type: Type of inverse document frequency (idf) to use for weights'
44
+ global component:
45
+
46
+ - "standard": idf = log(n_docs / df) + 1.0
47
+ - "smooth": idf = log(n_docs + 1 / df + 1) + 1.0, i.e. 1 is added
48
+ to all document frequencies, as if a single document containing
49
+ every unique term was added to the corpus.
50
+ - "bm25": idf = log((n_docs - df + 0.5) / (df + 0.5)), which is
51
+ a form commonly used in information retrieval that allows for
52
+ very common terms to receive negative weights.
53
+ - None: no global weighting is applied to local term weights.
54
+
55
+ dl_type: Type of document-length scaling to use for weights'
56
+ normalization component:
57
+
58
+ - "linear": dl (dls are already linear, so left as-is)
59
+ - "sqrt": dl => sqrt(dl)
60
+ - "log": dl => log(dl)
61
+ - None: no normalization is applied to local(*global?) weights
62
+
63
+ norm: If "l1" or "l2", normalize weights by the L1 or L2 norms, respectively,
64
+ of row-wise vectors; otherwise, don't.
65
+ min_df: Minimum number of documents in which a term must appear for it to be
66
+ included in the vocabulary and as a column in a transformed doc-term matrix.
67
+ If float, value is the fractional proportion of the total number of docs,
68
+ which must be in [0.0, 1.0]; if int, value is the absolute number.
69
+ max_df: Maximum number of documents in which a term may appear for it to be
70
+ included in the vocabulary and as a column in a transformed doc-term matrix.
71
+ If float, value is the fractional proportion of the total number of docs,
72
+ which must be in [0.0, 1.0]; if int, value is the absolute number.
73
+ max_n_terms: If specified, only include terms whose document frequency is within
74
+ the top ``max_n_terms``.
75
+ vocabulary_terms: Mapping of unique term string to unique term id, or
76
+ an iterable of term strings that gets converted into such a mapping.
77
+ Note that, if specified, vectorized outputs will include *only* these terms.
78
+
79
+ “lucene-style tfidf”: Adds a doc-length normalization to the usual local and global components.
80
+ Params: tf_type="linear", apply_idf=True, idf_type="smooth", apply_dl=True, dl_type="sqrt"
81
+
82
+ “lucene-style bm25”: Uses a smoothed idf instead of the classic bm25 variant to prevent weights on terms from going negative.
83
+ Params: tf_type="bm25", apply_idf=True, idf_type="smooth", apply_dl=True, dl_type="linear"
84
+ Attributes:
85
+ doc_term_matrix
86
+ Returns:
87
+ transform_fit'ted vectorizer
88
+ """
89
+ # make sure tokenized_docs is the right typing
90
+ try:
91
+ for xelm in iter(tokenized_docs):
92
+ for elm in iter(xelm):
93
+ assert isinstance(elm, str)
94
+ except AssertionError:
95
+ raise AssertionError(" tokenized_docs is not of the typing Iterable[Iterable[str]] ")
96
+ except Exception as e:
97
+ logger.error(e)
98
+ raise
99
+
100
+ vectorizer = Vectorizer(
101
+ # tf_type="linear", idf_type="smooth", norm="l2", min_df=3, max_df=0.95)
102
+ tf_type=tf_type,
103
+ idf_type=idf_type,
104
+ dl_type=dl_type,
105
+ norm=norm,
106
+ min_df=min_df,
107
+ max_df=max_df,
108
+ max_n_terms=max_n_terms,
109
+ vocabulary_terms=vocabulary_terms
110
+ )
111
+ doc_term_matrix = vectorizer.fit_transform(tokenized_docs)
112
+
113
+ gen_model.doc_term_matrix = doc_term_matrix
114
+
115
+ return vectorizer
radiobee/insert_spaces.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Insert spaces, mypython/split_chinese.py."""
2
+ import re
3
+
4
+
5
+ def insert_spaces(text: str) -> str:
6
+ """Insert space in Chinese characters.
7
+
8
+ >>> insert_spaces("test亨利it四世上")
9
+ ' test 亨 利 it 四 世 上 '
10
+ >>> insert_spaces("test亨利it四世上").strip().__len__()
11
+ 17
12
+
13
+ """
14
+ return re.sub(r"(?<=[a-zA-Z\d]) (?=[a-zA-Z\d])", "", text.replace("", " "))
radiobee/lists2cmat.py ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Convert two lists of str (texts) to correlation matrix."""
2
+ # from typing import Dict, Iterable, Optional, Union
3
+ from typing import Dict, Iterable, List, Optional, Union
4
+
5
+ import numpy as np
6
+ from textacy.representations import Vectorizer
7
+ from fastlid import fastlid
8
+
9
+ from radiobee.en2zh_tokens import en2zh_tokens
10
+ from radiobee.insert_spaces import insert_spaces
11
+ from radiobee.gen_model import gen_model
12
+ from radiobee.smatrix import smatrix
13
+
14
+
15
+ # fmt: off
16
+ def lists2cmat(
17
+ text1: Union[str, Iterable[str]],
18
+ text2: Union[str, Iterable[str]],
19
+ # text1: Union[str, List[str]],
20
+ # text2: Union[str, List[str]],
21
+ lang1: Optional[str] = None,
22
+ lang2: Optional[str] = None,
23
+ model: Vectorizer = None,
24
+ tf_type: str = 'linear',
25
+ idf_type: Optional[str] = "smooth",
26
+ # dl_type: Optional[str] = "sqrt", # "lucene-style tfidf"
27
+ dl_type: Optional[str] = None, #
28
+ norm: Optional[str] = "l2", # + "l2"
29
+ min_df: Union[int, float] = 1,
30
+ max_df: Union[int, float] = 1.0,
31
+ max_n_terms: Optional[int] = None,
32
+ vocabulary_terms: Optional[Union[Dict[str, int], Iterable[str]]] = None
33
+ ) -> np.ndarray:
34
+ # fmt: on
35
+ if isinstance(text1, str):
36
+ text1 = [text1]
37
+ if isinstance(text2, str):
38
+ text2 = [text2]
39
+
40
+ set_languages = fastlid.set_languages
41
+ fastlid.set_languages = ["en", "zh"]
42
+ if lang1 is None:
43
+ lang1, _ = fastlid(" ".join(text1))
44
+ if lang2 is None:
45
+ lang2, _ = fastlid(" ".join(text2))
46
+
47
+ # restore fastlid.set_languages
48
+ fastlid.set_languages = set_languages
49
+
50
+ # en2zh_tokens
51
+ def zh_tokens(textzh):
52
+ return [insert_spaces(elm).split() for elm in textzh]
53
+
54
+ if lang1 in ["zh"] and lang2 in ["en"]:
55
+ vec1 = zh_tokens(text1)
56
+ vec2 = en2zh_tokens(text2)
57
+ elif lang1 in ["zh"] and lang2 in ["zh"]:
58
+ vec1 = zh_tokens(text1)
59
+ vec2 = zh_tokens(text2)
60
+ elif lang1 in ["en"] and lang2 in ["en"]:
61
+ vec1 = en2zh_tokens(text1)
62
+ vec2 = en2zh_tokens(text2)
63
+
64
+ # if lang1 in ["en"] and lang2 in ["zh"]:
65
+ else:
66
+ vec1 = en2zh_tokens(text1)
67
+ vec2 = zh_tokens(text2)
68
+
69
+ if model is None:
70
+ model = gen_model(vec1)
71
+
72
+ cmat = smatrix(
73
+ vec1,
74
+ vec2,
75
+ model=model,
76
+ tf_type=tf_type,
77
+ idf_type=idf_type,
78
+ dl_type=dl_type,
79
+ norm=norm,
80
+ min_df=min_df,
81
+ max_df=max_df,
82
+ max_n_terms=max_n_terms,
83
+ vocabulary_terms=vocabulary_terms,
84
+ )
85
+
86
+ return np.array(cmat)
radiobee/loadtext.py ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Load file content to text.
3
+
4
+ Check encoding and load a file to text.
5
+
6
+ Win
7
+ Linux
8
+ apt install libmagic1
9
+
10
+ py -3.8 -m pip install python-magic-bin
11
+ py -3.8 -m pip install python-magic
12
+
13
+ import magic
14
+ magic.from_file("testdata/test.pdf")
15
+
16
+ original load_textrev
17
+ refer to load_paras.py
18
+ """
19
+ from typing import Optional, Union
20
+ import os
21
+ from pathlib import Path
22
+ import cchardet
23
+
24
+ from logzero import logger
25
+
26
+ # from detect_file import detect_file
27
+
28
+
29
+ def loadtext(filepath: Union[Path, str] = "") -> Optional[str]:
30
+ """Load file context to text.
31
+
32
+ Check encoding and load a file to text.
33
+
34
+ load_paras(filepath='') ==> paralist, lenlist =
35
+ """
36
+ if not filepath:
37
+ defaultdir = r"C:\dl\Dropbox\shuangyu_ku\txt-books"
38
+ defaultfile = r"Folding_Beijing-en.txt"
39
+
40
+ # filepath = defaultfile
41
+ # defaultdir = r'C:\dl\Dropbox\mat-dir\snippets-mat\pyqt'
42
+ # defaultfile = r'notes pyqt tkinter tktable.txt'
43
+
44
+ filepath = os.path.join(defaultdir, defaultfile)
45
+ filepath = Path(defaultdir) / defaultfile
46
+
47
+ filepath = Path(filepath)
48
+ if not filepath.is_file():
49
+ logger.error(" file [%s] does not exist or is not a file.", filepath)
50
+ # return None
51
+ raise Exception(" file [%s] does not exist or is not a file." % filepath)
52
+
53
+ # encoding = detect_file(filepath)
54
+ encoding = cchardet.detect(filepath.read_bytes()).get("encoding", "utf8")
55
+
56
+ if encoding is None:
57
+ raise Exception("cchardet.detect says it's not a text file.")
58
+
59
+ # cchardet: 'GB18030', no need for errors="ignore"
60
+ try:
61
+ text = filepath.read_text(encoding, errors="ignore")
62
+ except Exception as exc:
63
+ logger.error(" Opening %s resulted in errors: %s", filepath, exc)
64
+ raise
65
+
66
+ return text
67
+
68
+
69
+ def test1():
70
+ r"""
71
+ Tests default file.
72
+
73
+ defaultdir = r'D:\dl\Dropbox\mat-dir\snippets-mat\pyqt'
74
+ defaultfile = r'notes pyqt tkinter tktable.txt'
75
+ """
76
+ text = loadtext()
77
+ # eq_(2283, len(text))
78
+ # eq_(2283, len(text))
79
+
80
+ # del text
81
+ if text:
82
+ assert len(text) == 86423
83
+
84
+
85
+ def testgb():
86
+ r"""
87
+ Tests D:\dl\Dropbox\shuangyu_ku\txt-books\19部世界名著中英文对照版TXT
88
+ """
89
+ file = r"C:\dl\Dropbox\shuangyu_ku\txt-books\19部世界名著中英文对照版TXT" r"\爱丽丝漫游奇境记.txt"
90
+ text = loadtext(file)
91
+ if text:
92
+ # assert len(text) == 190913
93
+ assert len(text) == 188760
94
+
95
+ text0 = "ALICE'S ADVENTURES IN WONDERLAND\n CHAPTER 01 Down the Rabbit-Hole\n CHAPTER 02 The Pool of Tears\n CHAPTER 03 A Caucus-Race and a Long Tale\n CHAPTER 04 The Rabbit Sends in a Little Bill\n CHAPTER 05 Advice from a Caterpillar\n CHAPTER 06 Pig and Pepper\n CHAPTER 07 A Mad Tea-Party\n CHAPTER 08 The Queen's Croquet-Ground\n CHAPTER 09 The Mock Turtle's Story \n CHAPTER 10 The Lobster Quadrille\n CHAPTER 11 Who Stole the Tarts?\n CHAPTER 12 Alice's Evidence\n\n\n 爱 丽 丝 漫 游 奇 境 记 \n\n 第01章 " # NOQA
96
+
97
+ if text:
98
+ assert text0 == text[:500]
99
+
100
+
101
+ def testUTF_16LE():
102
+ r"""
103
+ Test 'E:\\beta_final_version\\build\\test_files\\files_for_testing_import\\Folding_Beijing_12.txt'.
104
+ """
105
+ # file = 'E:\\beta_final_version\\build\\test_files\\files_for_testing_import\\Folding_Beijing_12.txt' # NOQA
106
+ file = r"C:\dl\Dropbox\mat-dir\snippets-mat\pyqt\Sandbox\hp_beta-version_files\test_files\files_for_testing_import\Folding_Beijing_12.txt" # NOQA
107
+ file = r"C:\dl\Dropbox\mat-dir\pyqt\Sandbox\hp_beta-version_files\test_files\files_for_testing_import\Folding_Beijing_12.txt"
108
+
109
+ text = loadtext(file)
110
+ if text:
111
+ assert len(text) == 117871
112
+
113
+ # text0 = '\ufeffFolding Beijing\t北京折叠\n"by Hao Jingfang, translated by Ken Liu"\t郝景芳\n# 1.\t# 1\n"At ten of five in the m' # NOQA
114
+ text0 = r'Folding Beijing\t北京折叠\n"by Hao Jingfang, translated by Ken Liu"\t郝景芳\n# 1.\t# 1\n"At ten of five in the mo' # NOQA
115
+ text2 = 'Folding Beijing\t\xe5\x8c\x97\xe4\xba\xac\xe6\x8a\x98\xe5\x8f\xa0\r\n"by Hao Jingfang, translated by Ken Liu"\t\xe9\x83\x9d\xe6\x99\xaf\xe8\x8a\xb3\r\n# 1.\t# 1\r\n"At ten of five in the mo'
116
+
117
+ del text2
118
+
119
+ # if text: assert text0 == text[:100]
radiobee/mdx_dict_e2c.lzma ADDED
Binary file (1.18 MB). View file
radiobee/mdx_e2c.py ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Load mdx_dict_e2c c2e.
2
+
3
+ mdx_e2c = joblib.load("./mdx_dict_e2c.lzma")
4
+ mdx_c2e = joblib.load("./mdx_dict_e2c.lzma")
5
+ """
6
+ from pathlib import Path
7
+ from string import punctuation
8
+ import joblib
9
+
10
+ # keep "-"
11
+ punctuation = punctuation.replace("-", "")
12
+ c_dir = Path(__file__).parent
13
+
14
+ # lazy load in __init__.py like this?
15
+ # mdx_dict_e2c = importlib.import_module("mdx_dict_e2c")
16
+ # mdx_e2c = mdx_dict_e2c.mdx_e2c
17
+ # mdx_dict_c2e = importlib.import_module("mdx_dict_c2e")
18
+ # mdx_c2e = mdx_dict_c2e.mdx_c2e
19
+
20
+ mdx_dict_e2c = joblib.load(c_dir / "mdx_dict_e2c.lzma")
21
+ print("e2c lzma file loaded")
22
+
23
+ # memory = joblib.Memory("joblibcache", verbose=0)
24
+
25
+
26
+ # @memory.cache # no need, mdx_dict_e2c in RAM
27
+ def mdx_e2c(word: str) -> str:
28
+ """Fetch definition for word.
29
+
30
+ Args:
31
+ word: word to look up
32
+ Returns:
33
+ definition entry or word itself
34
+ >>> mdx_e2c("do").__len__()
35
+ 43
36
+ >>> mdx_e2c("我").strip()
37
+ '我'
38
+ """
39
+ word = word.strip(punctuation + " \t\n\r")
40
+ return mdx_dict_e2c.get(word.lower(), word)
radiobee/plot_df.py ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Plot pandas.DataFrame with DBSCAN clustering."""
2
+ # pylint: disable=invalid-name, too-many-arguments
3
+ # import numpy as np
4
+ import pandas as pd
5
+ import matplotlib.pyplot as plt
6
+ import seaborn as sns
7
+ from sklearn.cluster import DBSCAN
8
+
9
+ from logzero import logger
10
+
11
+ # turn interactive when in ipython session
12
+ if "get_ipython" in globals():
13
+ plt.ion()
14
+
15
+
16
+ # fmt: off
17
+ def plot_df(
18
+ df_: pd.DataFrame,
19
+ min_samples: int = 6,
20
+ eps: float = 10,
21
+ ylim: int = None,
22
+ xlabel: str = "en",
23
+ ylabel: str = "zh",
24
+ ) -> plt:
25
+ # fmt: on
26
+ """Plot df with DBSCAN clustering.
27
+
28
+ Args:
29
+ df_: pandas.DataFrame, with three columns columns=["x", "y", "cos"]
30
+ Returns:
31
+ matplotlib.pyplot: for possible use in gradio
32
+
33
+ plot_df(pd.DataFrame(cmat2tset(smat), columns=['x', 'y', 'cos']))
34
+ df_ = pd.DataFrame(cmat2tset(smat), columns=['x', 'y', 'cos'])
35
+
36
+ # sort 'x', axis 0 changes, index regenerated
37
+ df_s = df_.sort_values('x', axis=0, ignore_index=True)
38
+
39
+ # sorintg does not seem to impact clustering
40
+ DBSCAN(1.5, min_samples=3).fit(df_).labels_
41
+ DBSCAN(1.5, min_samples=3).fit(df_s).labels_
42
+
43
+ """
44
+ df_ = pd.DataFrame(df_)
45
+ if df_.columns.__len__() < 3:
46
+ logger.error(
47
+ "expected 3 columns DataFram, got: %s, cant proceed, returninng None",
48
+ df_.columns.tolist(),
49
+ )
50
+ return None
51
+
52
+ # take first three columns
53
+ columns = df_.columns[:3]
54
+ df_ = df_[columns]
55
+
56
+ # rename columns to "x", "y", "cos"
57
+ df_.columns = ["x", "y", "cos"]
58
+
59
+ sns.set()
60
+ sns.set_style("darkgrid")
61
+ # fig, (ax0, ax1) = plt.subplots(2, figsize=(11.69, 8.27))
62
+ fig, (ax0, ax1) = plt.subplots(1, 2, figsize=(11.69, 8.27))
63
+
64
+ fig.suptitle("alignment projection")
65
+ _ = DBSCAN(min_samples=min_samples, eps=eps).fit(df_).labels_ > -1
66
+ _x = DBSCAN(min_samples=min_samples, eps=eps).fit(df_).labels_ < 0
67
+
68
+ # ax0.scatter(df_[_].x, df_[_].y, marker='o', c='g', alpha=0.5)
69
+ # ax0.grid()
70
+ # print("ratio: %.2f%%" % (100 * sum(_)/len(df_)))
71
+
72
+ df_.plot.scatter("x", "y", c="cos", cmap="viridis_r", ax=ax0)
73
+
74
+ # clustered
75
+ df_[_].plot.scatter("x", "y", c="cos", cmap="viridis_r", ax=ax1)
76
+
77
+ # outliers
78
+ df_[_x].plot.scatter("x", "y", c="r", marker="x", alpha=0.6, ax=ax0)
79
+
80
+ # ax0.set_xlabel("")
81
+ # ax0.set_ylabel("zh")
82
+ ax0.set_xlabel("")
83
+ ax0.set_ylabel(ylabel)
84
+ xlim = len(df_)
85
+ ax0.set_xlim(0, xlim)
86
+ if ylim:
87
+ ax0.set_ylim(0, ylim)
88
+ ax0.set_title("max similarity along columns (outliers denoted by 'x')")
89
+
90
+ # ax1.set_xlabel("en")
91
+ # ax1.set_ylabel("zh")
92
+ ax1.set_xlabel(xlabel)
93
+ ax1.set_ylabel(ylabel)
94
+
95
+ ax1.set_xlim(0, xlim)
96
+ if ylim:
97
+ ax1.set_ylim(0, ylim)
98
+ ax1.set_title(f"potential aligned pairs ({round(sum(_) / len(df_), 2):.0%})")
99
+
100
+ return plt
radiobee/process_upload.py ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Process uploads."""
2
+ from typing import Union
3
+
4
+ from pathlib import Path
5
+ import tempfile
6
+ import cchardet
7
+ from logzero import logger
8
+
9
+
10
+ def process_upload(upload: Union[tempfile._TemporaryFileWrapper, bytes]) -> str:
11
+ """Process upload (fileobj or bytes(zip file: io.BytesIO further to zipfile.ZipFile)).
12
+
13
+ gr.inputs.File("file"): upload normal file
14
+ gr.inputs.File("bytes"): upload zip file
15
+
16
+ """
17
+ if isinstance(upload, bytes):
18
+ logger.warning("Not implemented, yet, for zip file")
19
+ return "Not implemented, yet, for zip file"
20
+
21
+ try:
22
+ fpath = Path(upload.name)
23
+ except Exception as e:
24
+ logger.error("Path(upload.name) error: %s", e)
25
+ return str(e)
26
+
27
+ suffixes = [
28
+ "",
29
+ ".txt",
30
+ ".text",
31
+ ".md",
32
+ ]
33
+ # check .txt .md ''(no suffix)
34
+ if fpath.suffix.lower() not in suffixes:
35
+ logger.warning('suffix: [%s] not in %s', fpath.suffix, suffixes)
36
+ # return "File type not supported, yet."
37
+
38
+ try:
39
+ data = Path(upload.name).read_bytes()
40
+ except Exception as e:
41
+ logger.error("Unable to read data from %s, errors: %s", fpath, e)
42
+ data = str(e).encode()
43
+
44
+ encoding = cchardet.detect(data).get("encoding", "utf8")
45
+ if encoding is not None:
46
+ try:
47
+ text = fpath.read_text(encoding)
48
+ except Exception as e:
49
+ logger.error("Unable to retrieve text, error: %s", e)
50
+ text = str(e)
51
+
52
+ # return f"{upload.name} {type(upload)}\n\n{text}"
53
+ # return f"{upload.name}\n{text}"
54
+ return text
55
+
56
+ # not able to cchardet: encoding is None, docx, pdf, epub, zip etc
57
+ logger.info("Trying docx...to be implemented")
58
+
59
+ # TODO
60
+
61
+ # return f"{upload.name} {type(upload)}\n\n..."
62
+ # return f"{upload.name}\n..."
63
+ return f"{upload.name}"
64
+
65
+
66
+ _ = ''' # colab gradio-file-inputs-upload.ipynb
67
+ # file_to_text/process_file
68
+ def zip_to_text(file_obj):
69
+ """
70
+ # zf = zipfile.ZipFile('german-recipes-dataset.zip')
71
+ zf = file_obj
72
+ namelist = zipfile.ZipFile.namelist(zf);
73
+ # filename = zf.open(namelist[0]);
74
+ file_contents = []
75
+ for filename in namelist:
76
+ with zf.open(filename) as fhandle:
77
+ file_contents.append(fhandle.read().decode())
78
+ """
79
+ # fileobj is <class 'tempfile._TemporaryFileWrapper'>
80
+
81
+ # gr.inputs.File("bytes")
82
+ if isinstance(file_obj, bytes):
83
+ data = file_obj.decode()
84
+ return f"{type(file_obj)}\n{dir(file_obj)}\n{data}"
85
+
86
+ # "file"/gr.inputs.File("file") file_obj.name: /tmp/READMEzm8hc5ze.md
87
+ data = Path(file_obj.name).read_bytes()
88
+ return f"{file_obj.name} {type(file_obj)}\n{dir(file_obj)} \n{data}"
89
+ # '''
radiobee/smatrix.py ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Generate a similarity matrix (doc-term score matrix) based on textacy.representation.Vectorizer.
2
+
3
+ refer also to fast-scores fast_scores.py and gen_model.py (sklearn.feature_extraction.text.TfidfVectorizer).
4
+ originally docterm_scores.py.
5
+ """
6
+ from typing import Dict, Iterable, Optional, Union
7
+ import numpy as np
8
+ from itertools import chain
9
+ from psutil import virtual_memory
10
+ from more_itertools import ilen
11
+
12
+ from textacy.representations import Vectorizer
13
+ # from textacy.representations.vectorizers import Vectorizer
14
+ from logzero import logger
15
+
16
+ # from smatrix.gen_model import gen_model
17
+ from radiobee.gen_model import gen_model
18
+
19
+
20
+ # fmt: off
21
+ def smatrix(
22
+ doc1: Iterable[Iterable[str]], # List[List[str]],
23
+ doc2: Iterable[Iterable[str]],
24
+ model: Vectorizer = None,
25
+ tf_type: str = 'linear',
26
+ idf_type: Optional[str] = "smooth",
27
+ # dl_type: Optional[str] = "sqrt", # "lucene-style tfidf"
28
+ dl_type: Optional[str] = None, #
29
+ norm: Optional[str] = "l2", # + "l2"
30
+ min_df: Union[int, float] = 1,
31
+ max_df: Union[int, float] = 1.0,
32
+ max_n_terms: Optional[int] = None,
33
+ vocabulary_terms: Optional[Union[Dict[str, int], Iterable[str]]] = None
34
+ ) -> np.ndarray:
35
+ # fmt: on
36
+ """Generate a doc-term score matrix based on textacy.representation.Vectorizer.
37
+
38
+ Args
39
+ doc1: tokenized doc of n1
40
+ doc2: tokenized doc of n2
41
+ model: if None, generate one ad hoc from doc1 and doc2 ("lucene-style tfidf").
42
+ rest: refer to textacy.representation.Vectorizer
43
+ Attributes
44
+ vectorizer
45
+
46
+ Returns
47
+ n1 x n2 similarity matrix of float numbers
48
+ """
49
+ # make sure doc1/doc2 is of the right typing
50
+ try:
51
+ for xelm in iter(doc1):
52
+ for elm in iter(xelm):
53
+ assert isinstance(elm, str)
54
+ except AssertionError:
55
+ raise AssertionError(" doc1 is not of the typing Iterable[Iterable[str]] ")
56
+ except Exception as e:
57
+ logger.error(e)
58
+ raise
59
+ try:
60
+ for xelm in iter(doc2):
61
+ for elm in iter(xelm):
62
+ assert isinstance(elm, str)
63
+ except AssertionError:
64
+ raise AssertionError(" doc2 is not of the typing Iterable[Iterable[str]] ")
65
+ except Exception as e:
66
+ logger.error(e)
67
+ raise
68
+
69
+ if model is None:
70
+ model = gen_model(
71
+ [*chain(doc1, doc2)],
72
+ tf_type=tf_type,
73
+ idf_type=idf_type,
74
+ dl_type=dl_type,
75
+ norm=norm,
76
+ min_df=min_df,
77
+ max_df=max_df,
78
+ max_n_terms=max_n_terms,
79
+ vocabulary_terms=vocabulary_terms
80
+ )
81
+ # docterm_scores.model = model
82
+ smatrix.model = model
83
+
84
+ # a1 = dt.toarray(), a2 = doc_term_matrix.toarray()
85
+ # np.all(np.isclose(a1, a2))
86
+
87
+ dt1 = model.transform(doc1)
88
+ dt2 = model.transform(doc2)
89
+
90
+ # virtual_memory().available / 8: 64bits float
91
+ require_ram = ilen(iter(doc1)) * ilen(iter(doc2)) * 8
92
+ if require_ram > virtual_memory().available:
93
+ logger.warning("virtual_memory().available: %s", virtual_memory().available)
94
+ logger.warning("memory required: %s", require_ram)
95
+
96
+ if require_ram > virtual_memory().available * 10:
97
+ logger.warning("You're likely to encounter memory problem, such as slowing down response and/or OOM.")
98
+
99
+ # return dt1.doc(dt2.T)
100
+ return dt2.toarray().dot(dt1.toarray().T)
requirements.txt ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ chardet
2
+ certifi
3
+ charset-normalizer
4
+ idna
5
+ typing-extensions
6
+ sklearn
7
+ textacy
8
+ logzero
9
+ more_itertools
10
+ psutil
11
+ seaborn
12
+ cchardet
13
+ tabulate
14
+ git+https://github.com/ffreemt/fast-langid
15
+ dotenv
16
+ varname
17
+ textacy
run-pyright.bat ADDED
@@ -0,0 +1 @@
 
1
+ nodemon -w radiobee -w tests -x pyright radiobee tests
run-radiobee.bat ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ REM nodemon -V -w radiobee -x "sleep 3 && python -m radiobee"
2
+ REM nodemon -V -w radiobee -x python -m radiobee
3
+ nodemon -V -w radiobee -x py -3.8 -m radiobee
start-radiobee.bat ADDED
@@ -0,0 +1 @@
 
1
+ start "radiobee" run-radiobee
tests/__init__.py ADDED
@@ -0,0 +1 @@
 
1
+ """Init."""
tests/test_en.txt ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Wuthering Heights
2
+
3
+
4
+ --------------------------------------------------------------------------------
5
+
6
+ Chapter 2
7
+
8
+ Chinese
9
+
10
+
11
+ Yesterday afternoon set in misty and cold. I had half a mind to spend it by my study fire, instead of wading through heath and mud to Wuthering Heights. On coming up from dinner, however (N.B. I dine between twelve and one o'clock; the housekeeper, a matronly lady, taken as a fixture along with the house, could not, or would not, comprehend my request that I might be served at five), on mounting the stairs with this lazy intention, and stepping into the room, I saw a servant girl on her knees surrounded by brushes and coal-scuttles, and raising an infernal dust as she extinguished the flames with heaps of cinders. This spectacle drove me back immediately; I took my hat, and, after a four-miles' walk, arrived at Heathcliff's garden gate just in time to escape the first feathery flakes of a snow shower.
12
+
13
+ On that bleak hill top the earth was hard with a black frost, and the air made me shiver through every limb. Being unable to remove the chain, I jumped over, and, running up the flagged causeway bordered with straggling gooseberry bushes, knocked vainly for admittance, till my knuckles tingled and the dogs howled.
14
+
15
+ `Wretched inmates!' I ejaculated mentally, `you deserve perpetual isolation from your species for your churlish inhospitality. At least, I would not keep my doors barred in the day time. I don't care--I will get in!' So resolved, I grasped the latch and shook it vehemently. Vinegar-faced Joseph projected his head from a round window of the barn.
16
+
17
+ `Whet are ye for?' he shouted. `T' maister's dahn i' t' fowld. Go rahnd by th' end ut' laith, if yah went tuh spake tull him.'
18
+
19
+ `Is there nobody inside to open the door?' I hallooed, responsively.
20
+
21
+ `They's nobbut t' missis; and shoo'll nut oppen't an ye mak yer flaysome dins till neeght.'
22
+
23
+ `Why? Cannot you tell her who I am, eh, Joseph?'
24
+
25
+ `Nor-ne me! Aw'll hae noa hend wi't,' muttered the head, vanishing.
26
+
27
+ The snow began to drive thickly. I seized the handle to essay another trial; when a young man without coat, and shouldering a pitchfork, appeared in the yard behind. He hailed me to follow him, and, after marching through a wash-house, and a paved area containing a coal shed, pump, and pigeon cot, we at length arrived in the huge, warm, cheerful apartment, where I was formerly received. It glowed delightfully in the radiance of an immense fire, compounded of coal, peat, and wood; and near the table, laid for a plentiful evening meal, I was pleased to observe the `missis', an individual whose existence I had never previously suspected. I bowed and waited, thinking she would bid me take a seat. She looked at me, leaning back in her chair, and remained motionless and mute.
28
+
29
+ `Rough weather!' I remarked. `I'm afraid, Mrs Heathcliff, the door must bear the consequence of your servants' leisure attendance: I had hard work to make them hear me.'
30
+
31
+ She never opened her mouth. I stared--she stared also: at any rate, she kept her eyes on me in a cool, regardless manner, exceedingly embarrassing and disagreeable.
32
+
33
+ `Sit down,' said the young man gruffly. `He'll be in soon.'
34
+
35
+ I obeyed; and hemmed, and called the villain Juno, who deigned, at this second interview, to move the extreme tip of her tail, in token of owning my acquaintance.
36
+
37
+ `A beautiful animal!' I commenced again. `Do you intend parting with the little ones, madam?'
38
+
39
+ `They are not mine,' said the amiable hostess, more repellingly than Heathcliff himself could have replied.
40
+
41
+ `Ah, your favourites are among these?' I continued, turning to an obscure cushion full of something like cats.
42
+
43
+ `A strange choice of favourites!' she observed scornfully.
44
+
45
+ Unluckily, it was a heap of dead rabbits. I hemmed once more, and drew closer to the hearth, repeating my comment on the wildness of the evening.
46
+
47
+ `You should not have come out,' she said, rising and reaching from the chimney-piece two of the painted canisters.
48
+
49
+ Her position before was sheltered from the light; now, I had a distinct view of her whole figure and countenance. She was slender, and apparently scarcely past girlhood: an admirable form, and the most exquisite little face that I have ever had the pleasure of beholding; small features, very fair; flaxen ringlets, or rather golden, hanging loose on her delicate neck; and eyes, had they been agreeable in expression, they would have been irresistible: fortunately for my susceptible heart, the only sentiment they evinced hovered between scorn, and a kind of desperation, singularly unnatural to be detected there. The canisters were almost out of her reach; I made a motion to aid her; she turned upon me as a miser might turn if anyone attempted to assist him in counting his gold.
50
+
51
+ `I don't want your help,' she snapped; `I can get them for myself.'
52
+
53
+ `I beg your pardon!' I hastened to reply.
54
+
55
+ `Were you asked to tea?' she demanded, tying an apron over her neat black frock, and standing with a spoonful of the leaf poised over the pot.
56
+
57
+ `I shall be glad to have a cup,' I answered.
58
+
59
+ `Were you asked?' she repeated.
60
+
61
+ `No,' I said, half smiling. `You are the proper person to ask me.'
62
+  
63
+
64
+
65
+ Contents PreviousChapter
66
+ NextChapter
67
+
68
+
69
+ Homepage
tests/test_files2df.py ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Test files2df."""
2
+ from pathlib import Path
3
+ import tempfile
4
+ from radiobee.files2df import files2df
5
+
6
+ def test_files2df():
7
+ """Test files2df with tests/test_en.txt tests/test_zh.txt."""
8
+ file1_ = "tests/test_en.txt"
9
+ file2_ = "tests/test_zh.txt"
10
+ with open(file1_, 'rb') as fh1, open(file2_, 'rb') as fh2:
11
+ file1 = tempfile._TemporaryFileWrapper(fh1, file1_)
12
+ file2 = tempfile._TemporaryFileWrapper(fh2, file2_)
13
+ assert Path(file1.name).is_file()
14
+ assert Path(file2.name).is_file()
15
+
16
+ df = files2df(file1, file2)
17
+
18
+ assert df.iloc[1, 0] == "Wuthering Heights"
19
+ assert df.iloc[1, 1] == "呼啸山庄"
20
+
21
+
22
+ def test_files2df_file2none():
23
+ """Test files2df with tests/test_en.txt None."""
24
+ file1_ = "tests/test_en.txt"
25
+ file2 = None
26
+ with open(file1_, 'rb') as fh1:
27
+ file1 = tempfile._TemporaryFileWrapper(fh1, file1_)
28
+ assert Path(file1.name).is_file()
29
+
30
+ df = files2df(file1, file2)
31
+
32
+ assert df.iloc[1, 0] == "Wuthering Heights"
33
+ assert df.iloc[1, 1] == ""
tests/test_lists2cmat.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Test lists2cmat."""
2
+ # pylint: disable=invalid-name
3
+ from itertools import zip_longest
4
+ from fastlid import fastlid
5
+ from radiobee.loadtext import loadtext
6
+ from radiobee.lists2cmat import lists2cmat
7
+
8
+ file1 = "data/test_en.txt"
9
+ file2 = "data/test_zh.txt"
10
+
11
+ # assume English or Chinese
12
+ fastlid.set_languages = ["en", "zh", ]
13
+
14
+ text1 = loadtext(file1)
15
+ text2 = loadtext(file2)
16
+
17
+ lang1, _ = fastlid(text1)
18
+ lang2, _ = fastlid(text2)
19
+
20
+
21
+ def test_lists2cmat():
22
+ """Test lists2cmat."""
23
+
24
+ lst1, lst2 = [], []
25
+
26
+ if text1:
27
+ lst1 = [_.strip() for _ in text1.splitlines() if _.strip()]
28
+ if text2:
29
+ lst2 = [_.strip() for _ in text2.splitlines() if _.strip()]
30
+
31
+ # en zh
32
+ len(lst1) == 33, len(lst2) == 36
33
+
34
+ # cmat = texts2cmat(lst1, lst2, lang1, lang2)
35
+ cmat = lists2cmat(lst1, lst2, lang1, lang2)
36
+
37
+ assert cmat.shape == (36, 33)
38
+
39
+ cmat21 = lists2cmat(lst2, lst1, lang2, lang1)
40
+
41
+ assert cmat21.shape == (33, 36)
42
+ assert lists2cmat(lst2, lst1).mean() > 0.05 # 0.09
tests/test_loadtext.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Test loadtext."""
2
+ import pytest
3
+
4
+ from radiobee.loadtext import loadtext
5
+
6
+
7
+ def test_loadtext():
8
+ _ = loadtext("data/test_en.txt").splitlines()
9
+ _ = [elm for elm in _ if elm.strip()]
10
+ assert len(_) == 33
11
+
12
+
13
+ @pytest.mark.xfail
14
+ def test_loadtext_from_dir():
15
+ """Test test_loadtext_from_dir."""
16
+ _ = loadtext(".")
tests/test_main.py ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Test __main__.py."""
2
+ # pylint: disable=invalid-name
3
+ import tempfile
4
+ from fastlid import fastlid
5
+
6
+ # globals()["file2text"] = getattr(importlib.import_module(f"{radiobee.__name__}.file2text"), "file2text")
7
+ # from radiobee.process_upload import process_upload # same as file2text
8
+ from radiobee.files2df import files2df
9
+ from radiobee.file2text import file2text
10
+ from radiobee.lists2cmat import lists2cmat
11
+ from radiobee.cmat2tset import cmat2tset
12
+
13
+ file1loc = "data/test_zh.txt"
14
+ file2loc = "data/test_en.txt"
15
+
16
+ file1 = tempfile._TemporaryFileWrapper(open(file1loc, "rb"), file1loc)
17
+ file2 = tempfile._TemporaryFileWrapper(open(file2loc, "rb"), file2loc)
18
+
19
+ def test_file2file1():
20
+ """Test cmat file2 file1."""
21
+ # logger.info("file1: *%s*, file2: *%s*", file1, file2)
22
+ logger.info("file1.name: *%s*, file2.name: *%s*", file1.name, file2.name)
23
+
24
+ text1 = file2text(file1)
25
+ text2 = file2text(file2)
26
+
27
+ lang1, _ = fastlid(text1)
28
+ lang2, _ = fastlid(text2)
29
+
30
+ lst1 = [elm.strip() for elm in text1.splitlines() if elm.strip()]
31
+ lst2 = [elm.strip() for elm in text2.splitlines() if elm.strip()]
tests/test_zh.txt ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 呼啸山庄
2
+
3
+ --------------------------------------------------------------------------------
4
+
5
+ 第二章
6
+
7
+ 英文
8
+
9
+
10
+ 昨天下午又冷又有雾。我想就在书房炉边消磨一下午,不想踩着杂草污泥到呼啸山庄了。
11
+
12
+ 但是,吃过午饭(注意——我在十二点与一点钟之间吃午饭,而可以当作这所房子的附属物的管家婆,一位慈祥的太太却不能,或者并不愿理解我请求在五点钟开饭的用意),在我怀着这个懒惰的想法上了楼,迈进屋子的时候,看见一个女仆跪在地上,身边是扫帚和煤斗。她正在用一堆堆煤渣封火,搞起一片弥漫的灰尘。这景象立刻把我赶回头了。我拿了帽子,走了四里路,到达了希刺克厉夫的花园口口,刚好躲过了一场今年初降的鹅毛大雪。
13
+
14
+ 在那荒凉的山顶上,土地由于结了一层黑冰而冻得坚硬,冷空气使我四肢发抖。我弄不开门链,就跳进去,顺着两边种着蔓延的醋栗树丛的石路跑去。我白白地敲了半天门,一直敲到我的手指骨都痛了,狗也狂吠起来。
15
+
16
+ “倒霉的人家!”我心里直叫,“只为你这样无礼待客,就该一辈子跟人群隔离。我至少还不会在白天把门闩住。我才不管呢——我要进去!”如此决定了。我就抓住门闩,使劲摇它。苦脸的约瑟夫从谷仓的一个圆窗里探出头来。
17
+
18
+ “你干吗?”他大叫。“主人在牛栏里,你要是找他说话,就从这条路口绕过去。”
19
+
20
+ “屋里没人开门吗?”我也叫起来。
21
+
22
+ “除了太太没有别人。你就是闹腾到夜里,她也不会开。”
23
+
24
+ “为什么?你就不能告诉她我是谁吗,呃,约瑟夫?”
25
+
26
+ “别找我!我才不管这些闲事呢,”这个脑袋咕噜着,又不见了。
27
+
28
+ 雪开始下大了。我握住门柄又试一回。这时一个没穿外衣的年轻人,扛着一根草耙,在后面院子里出现了。他招呼我跟着他走,穿过了一个洗衣房和一片铺平的地,那儿有煤棚、抽水机和鸽笼,我们终于到了我上次被接待过的那间温暖的、热闹的大屋子。煤、炭和木材混合在一起燃起的熊熊炉火,使这屋子放着光彩。在准备摆上丰盛晚餐的桌旁,我很高兴地看到了那位“太太”,以前我从未料想到会有这么一个人存在的。我鞠躬等候,以为她会叫我坐下。她望望我,往她的椅背一靠,不动,也不出声。
29
+
30
+ “天气真坏!”我说,“希刺克厉夫太太,恐怕大门因为您的仆人偷懒而大吃苦头,我费了好大劲才使他们听见我敲门!”
31
+
32
+ 她死不开口。我瞪眼——她也瞪眼。反正她总是以一种冷冷的、漠不关心的神气盯住我,使人十分窘,而且不愉快。
33
+
34
+ “坐下吧,”那年轻人粗声粗气地说,“他就要来了。”
35
+
36
+ 我服从了;轻轻咳了一下,叫唤那恶狗朱诺。临到第二次会面,它总算赏脸,摇起尾巴尖,表示认我是熟人了。
37
+
38
+ “好漂亮的狗!”我又开始说话。“您是不是打算不要这些小的呢,夫人?”
39
+
40
+ “那些不是我的,”这可爱可亲的女主人说,比希刺克厉夫本人所能回答的腔调还要更冷淡些。
41
+
42
+ “啊,您所心爱的是在这一堆里啦!”我转身指着一个看不清楚的靠垫上那一堆像猫似的东西,接着说下去。
43
+
44
+ “谁会爱这些东西那才怪呢!”她轻蔑地说。
45
+
46
+ 倒霉,原来那是堆死兔子。我又轻咳一声,向火炉凑近些,又把今晚天气不好的话评论一通。
47
+
48
+ “你本来就不该出来。”她说,站起来去拿壁炉台上的两个彩色茶叶罐。
49
+
50
+ 她原先坐在光线被遮住的地方,现在我把她的全身和面貌都看得清清楚楚。她苗条,显然还没有过青春期。挺好看的体态,还有一张我生平从未有幸见过的绝妙的小脸蛋。五官纤丽,非常漂亮。淡黄色的卷发,或者不如说是金黄色的,松松地垂在她那细嫩的颈上。至于眼睛,要是眼神能显得和悦些,就要使人无法抗拒了。对我这容易动情的心说来倒是常事,因为它们所表现的只是在轻蔑与近似绝望之间的一种情绪,而在那张脸上看见那样的眼神是特别不自然的。
51
+
52
+ 她简直够不到茶叶罐。我动了一动,想帮她一下。她猛地扭转身向我,像守财奴看见别人打算帮他数他的金子一样。
53
+
54
+ “我不要你帮忙,”她怒气冲冲地说,“我自己拿得到。”
55
+
56
+ “对不起!”我连忙回答。
57
+
58
+ “是请你来吃茶的吗?”她问,把一条围裙系在她那干净的黑衣服上,就这样站着,拿一匙茶叶正要往茶壶里倒。
59
+
60
+ “我很想喝杯茶。”我回答。
61
+
62
+ “是请你来的吗?”她又问。
63
+
64
+ “没有,”我说,勉强笑一笑。“您正好请我喝茶。”
65
+
66
+  
67
+
68
+
69
+ 目录
70
+ 上一章
71
+ 下一章
72
+
73
+
74
+ 返回首页