Dobrodružství

Dobrodružství
3 dny

Most people visiting Eleuthera never know this cave exists, which seems like a real shame. Hidden off Queen's Highway near the Hatchet Bay silos, it's the largest cave system on the island and one of the more genuinely weird and wonderful things you can do in the Bahamas. A descent down a set of rough stairs puts you in the first chamber, where natural light still filters in and a few stalactites and stalagmites give you a preview of what's ahead. Keep going and things get considerably more dramatic. The cave runs about a mile underground across three levels, with formations that locals and visitors have given names like "Cathedral Hall," "The Wizard's Hat," "Wedding Cake," and "Frozen Waterfall." A thin guide string runs along the floor to keep you on track. The cave was described in an 1874 issue of Harper's Monthly as "a cave extending 1,100 feet underground enriched by stalactites of a brilliant brown hue," which is still pretty accurate. At one point you'll need to descend a ladder to reach the second level, where the real formations are. The cave is also home to colonies of leaf-nosed bats, which mostly ignore visitors but will remind you they are there if you make enough noise. And then there's the graffiti. Some of it is genuinely fascinating: signatures carved with carbide lamps dating back to the 1870s, left by people who made their way in here before electricity or automobiles existed on the island. The more recent spray-painted stuff is considerably less charming, but it thins out the deeper in you go. The Lucayan Arawak people, who inhabited the Bahamas before European contact, believed caves were gateways to the afterlife. Archaeological evidence suggests they used Hatchet Bay Cave for burial purposes, which adds a certain mood to the whole experience. The cave is unmanaged, free, and about as far from a tourist attraction as you can get while still being a place people actually visit. It's worth every minute.

22.05.2026 14:00:00

Dobrodružství
3 dny
Dobrodružství
3 dny

In 1891, the National Chautauqua Assembly established Glen Echo Park, just outside of Washington, DC, as a school for liberal arts and sciences, an endeavor that lasted only one year. By the early 1900s, the site had become Glen Echo Amusement Park, catering to the Capital’s pleasure seekers. Although the amusement park rides are long gone, Glen Echo Park still operates its iconic Dentzel Carousel—a lasting reminder of the park’s vibrant history. Today, Glen Echo Park’s century-old Carousel stands as one of the world’s oldest merry-go-rounds, still in operation and at its original location. Constructed by the Dentzel Carousel Company of Germantown, Pennsylvania, in 1921, it attracts more than 50,000 visitors each year and is listed on the National Register of Historic Places. Classified as a “menagerie carousel” due to its number and variety of animals, the Carousel features 52 hand-carved wooden animals and two circus chariots. Its menagerie includes 40 horses, several rabbits and ostriches, a lion, a tiger, a giraffe, and a deer. It spins at a relatively speedy five turns per minute to the accompaniment of a 105-year-old Wurlitzer organ. In 1983, Rosa Patton began a 24-year restoration of the Carousel, returning its animals, organ, canopy building, and floor to their original paint colors. The restoration was completed in 2003, ensuring that its original charm would endure for future generations. The Carousel also became a symbol of social change. During the summer of 1960, it was the site of protests in the American Civil Rights Movement. On June 30, 1960, black students from Howard University in Washington, DC, boarded the Carousel in defiance of the Park’s segregation policies. When confronted by Park security, the students refused to leave, prompting the operator to stop the ride. After two and 1/2 hours, five students were arrested for “criminal trespass.” Protests continued at and around the Park throughout the rest of the summer. When the Park reopened for the 1961 season, it was desegregated. The events at Glen Echo set the stage for legal change. They culminated in the landmark 1964 Supreme Court decision, Griffin v. Maryland, in which the Court ruled that the arrests of Black patrons by a state-commissioned deputy sheriff, albeit working as a security guard at a private establishment, constituted state-enforced segregation violating the 14th Amendment. This case, along with others, set an important legal precedent for the Civil Rights Act of 1964.

22.05.2026 10:30:00

Dobrodružství
4 dny

In downtown Dallas at 501 Elm Street, a few steps from Dealey Plaza, sits a two-story museum dedicated to money. Not the kind of museum where currency lives behind glass. Visitors here are handed a route through 28 exhibits and told to touch everything. Some of it is pure spectacle. There is a booth where dollar bills shower down on whoever steps inside. There is a vault visitors can attempt to break into by dodging a laser grid. There is an 80s investment banker who reads guests' financial futures with great confidence and questionable accuracy. Other exhibits are quieter and more curious. One small room asks visitors to barter their way to what they need without any money at all. Most adults give up within a couple of minutes and rediscover why people invented currency. Another lines a wall with real and counterfeit bills and asks visitors to pick out the fakes. A third tells the story of Mademoiselle Zélie, a 19th-century French singer who was paid for a Pacific island tour in livestock and produce: three pigs, twenty-three turkeys, five thousand coconuts, and fifteen hundred oranges, among other things. Tucked between the photo ops are panels on the real history of money. Bronze knife-shaped and spade-shaped Chinese coins from 2,700 years ago. The story of Y'all Street, the Texas stock exchange opening in Dallas. Why gold became valuable in the first place (it doesn't rust, it's rare, and it's easy to shape). The space rewards curiosity at any age. Children come for the cash shower. Adults stay for the bartering room.

21.05.2026 16:00:00

Dobrodružství
4 dny

As the terminus of the world’s first passenger train line, Manchester was at the forefront of nineteenth century rail development, and that included the construction of a considerable amount of rail infrastructure around the city.  The neighborhood named Castlefield on the southwest side of the city center not only features the world’s oldest remaining passenger railway station but also several historic viaducts and bridges. The 330 m long viaduct formally named the Castlefield Viaduct, which originally connected the former Manchester Central Station (now a conference center named Manchester Central) to the rail network, is distinctly different from most of the other brick viaducts around Manchester.  Heenan and Froude (the same company that built the Blackpool Tower) constructed the Castlefield Viaduct in 1892 using primarily cast iron and wrought iron for a significant section of the viaduct, although these connect to more traditional brick sections.  The sections constructed with iron stand out; its silvery cylindrical iron pillars straddle the canals while holding up the viaduct’s metal parapet with its lattice-like walls. The viaduct would be in used until 1969, when the rail line closed.  After that point, the viaduct was essentially closed off for a few decades, although it was still maintained.  As the neighborhood was gentrified over the following decades, the viaduct was eventually seen as a local landmark, and it would even feature in shows such as Coronation Street and Peaky Blinders.  Recognizing the architectural importance of the viaduct, English Heritage granted it Grade II status in 1988, ensuring that the structure could not be demolished. However, the biggest change in the viaduct’s history was in the 2020s, when the National Trust set up an elevated garden on the viaduct that was inspired at least in part by the High Line in New York City.  This garden was opened to the public in 2022.  Visitors can now walk among planters filled with flowers, trees, and other cultivated plants enclosed within the nineteenth century iron lattice structure while also enjoying the elevated views of the Castlefield neighborhood (including the reconstructed Roman fort) as well as the cityscape beyond.

21.05.2026 12:00:00

Dobrodružství
5 dní

Listen and subscribe on Apple Podcasts, Spotify, and all major podcast apps. Kelly McEvers: Today we’re going to talk about a candy store in Harpers Ferry, West Virginia. And about how candy stores have always played a big role in the town’s history. Back in the 1840s, a German immigrant named Frederick Roeder set up a little sweet shop in Harpers Ferry. He sold cakes, candies, and pies and lived right upstairs for about 15 years. But then came the morning of July 4, 1861 .By that time, the Civil War had arrived. Union troops were moving in. Roeder ventured outside his shop to check out the scene. Some say to get a look at the Union flag flying just across the river. He was a Union sympathizer himself. He was hit by a ricocheting bullet. And then he died. Which means the town’s first civilian casualty of the Civil War was the local candy shop owner. And today, the connection between candy and history is still going strong in Harpers Ferry. There’s a plaque marking the site of Roeder’s old store. And just a few steps away down a street called Hog’s Alley is a place called True Treats. It’s a candy shop, but that doesn’t tell the whole story.It’s also sort of an edible timeline of the history of candy. Susan Benjamin: We are not a candy store. We’re a museum where you can eat the displays. I’m Kelly McEvers and this is Atlas Obscura, a celebration of the world’s strange, incredible, and wondrous places. And today’s episode is brought to you in partnership with the West Virginia Department of Tourism. And today we’re going to eat our history. We will meet candy scholar Susan Benjamin, who founded what she calls the only research-based historic candy shop in the country. She’ll introduce us to some surprising sweets that have shaped American history, from abolitionist sugars to World War I’s chocolate energy bars. That’s coming up after this. This is an edited transcript of the Atlas Obscura Podcast: a celebration of the world’s strange, incredible, and wondrous places. Find the show on Apple Podcasts, Spotify, and all major podcast apps. Kelly: Susan Benjamin is a candy scholar. So basically, she has the job that every kid dreams about. And it’s no fluke that she ended up in Harpers Ferry. History buffs will recognize the name. It is where abolitionist John Brown led his famous raid back in 1859. Visitors can still see the armory he raided and lots of Civil War sites. Downtown Harpers Ferry even looks a lot like it did back in the 1800s—narrow streets and old brick buildings. It’s the perfect place for true treats, which bills itself as the country’s only research-based historic candy store. Susan: Our retail store is located in a building that opened in 1843 and was part of the Civil War itself. So you can imagine just how beautiful it is, not updated at all other than to keep the building straight. Kelly: That’s Susan. Susan: When you walk into our store, people think it’s really cute and really “old-time” and expect to see, “Wow, I’m so happy to see a real retro candy store!” Whoa, no, we’re not retro! We have retro, but we start before then. Kelly: What Susan calls “retro candy” is stuff you might have found in the Five and Dime store: gummy sharks, lemon sours, tangerine drops, circus peanuts, stuff like that. But at True Treats, there are also older and less familiar sweets: beet sugar crystals, World War I ration bars, medicinal hard candies. In fact, the oldest products on the shelves come from thousands of years ago, like something called pastelli, which looks like peanut brittle, but with sesame seeds. Susan says Homer describes it in The Iliad as a honey and sesame pie. This is a researcher’s approach to candy. In another life, Susan worked under the Clinton and Bush White Houses on communication initiatives. And before that, she was an academic in Massachusetts. Susan: I’m from Boston. Who would know? Kelly: But that was before she came down to West Virginia and fell in love with the history of candy. She’s even written a book on the subject called Sweet as Sin: The Unwrapped Story of How Candy Became America’s Favorite Pleasure. And she arranges the shop in a very specific way. Susan: You can start first in history and walk chronologically all the way through the various time periods of candy. The history’s on the label, and what’s really important is that people get an experience of the history of candy because it’s never what they expect. Kelly: Susan says the way to experience the shop is to walk through, pick out things that interest you, then go sit down in the front of the shop and eat your way through history. Susan: Often whole families or groups of people sitting around little tables, sampling everything and reading the labels. And if I’m there, I’ll come over, or one of my employees who knows the stories will come over, and we’ll tell them a little bit more about it. Kelly: There are hundreds of different candies and teas and other sweets in the shop and on their website. So a lot to choose from. But to give you a little sample, let’s just take a quick walk through the timeline of candy history in chronological order. The oldest section comes first. You’ve got the sesame brittle candies from The Iliad, but also a lot of ingredients native to the Americas. There are candies made with maple sugar. Native Americans were processing maple sap into sugars and sweets long before the Europeans arrived. And… Susan: … the cacao nib, which is really important because that comes from Mesoamerica and the Native Americans. Kelly: Chocolate really took off in colonial America, specifically as a hot beverage. In other words, hot chocolate. People would mix it into milk or cream and grate spices on top. Martha Washington made hers out of steeped cacao shells. Susan says that as the Revolutionary War got underway, the drink became political. Susan: Chocolate was actually a vehicle during the American Revolution in their boycotting of teas, of the British tea, and they needed alternatives. And one of the alternatives was chocolate, and they really pushed, “Everybody’s got to have chocolate. They’ve got to drink that.” Kelly: In the 1780s, Thomas Jefferson even declared that chocolate would one day become a more popular drink than coffee or tea in the U.S. It didn’t happen, but not a bad idea. Moving on to the 1800s, the Civil War is coming. An intriguing story that pops out from this section also has to do with boycotts. As the country became more and more divided over slavery, people looked for ways to strike at the system economically. Susan: What happened with the abolitionists is they looked for a number of ways to boycott the economy of slavery, by taking away the produce or finding alternatives to the produce that were funding slavery through its sales, and obviously cane sugar was a big one. So what they did instead was they found alternatives and they promoted those. Kelly: Groups called “free produce societies” formed and promoted alternatives to cane sugar like honey, corn syrup, and syrup made from a grain called sorghum. The most interesting-looking alternative can be found at True Treats. It comes in a small glass jar and looks almost like golden raisins: these little orange pink crystals. Susan: Beet sugar! So today, a huge amount of the sugar that we have is actually beet sugar, and that goes in the candy. Kelly: Moving on to the early 1900s, things start to look a little more recognizable. We start to see candies wrapped up with brand names as industrialization comes to the candy world. Susan: But at that point you would have things called cough drops, the Pine Brothers cough drops, the Smith Brothers cough drops. Is it a medicine or is it a candy? Well, yes, both, right? And today when we take these Halls or these various medicines that have been around for a really long time, what you’re getting is essentially a candy. So why worry about it, you know, but there was that crossover. Kelly: There are also some interesting chocolate bars, including some brands that are new to me, like one called Goldenberg’s Peanut Chews. It looks a little like a Payday, but it’s made of peanuts and molasses. This one actually has a military connection. Susan: During World War I, people were making candy bars, and they were called “stuffed chocolate,” but they were basically candy bars that didn’t just have chocolate but had nuts and caramel. And they wound up being in one of the first rations during the First World War. So they sent Goldenberg’s Peanut Chews and a couple others. They sent it off to the World War I soldiers.They came back saying, “I love these candy bars. These are so great.” Kelly: Including these chocolate bars in rations wasn’t just for a morale boost. It was meant to be a quick source of energy: high fat, high calorie, easy to eat. And chocolate bars continued to be known for that after the war was over. Susan: During the Depression, they were marketed as an inexpensive meal in a bar. That’s how they marketed them. Kelly: Fun fact: The Mr. Goodbar was one of these. It was created by the Hershey Company in 1925 and advertised as a tasty lunch. By this time, we’re coming back around to the modern age or close to it. This is when we get into the retro candy, the kind of stuff you see at the Five and Dime or in your parents’ or grandparents’ candy dishes: Malted milk balls, rock candy, bubble gum cigarettes (you really don’t see those anymore). This section, Susan says, is a crowd favorite. Susan: What they really, really love is when they read the story of the retro candy. And what they do with that, and what they do with eating that is they talk about their grandparents, and they talk about where they lived, and they talk about the candy store on the corner. Kelly: For Susan, this is what the store is all about: Learning about the past in a new and unusual way. Susan: It’s a visceral experience of history. When you eat the candies, you know where they’re from, when they’re from, a little bit about the role they played, and then you get to be able to smell, taste, and enjoy it, and get more if you want, you know, it’s that kind of experience. Kelly: And maybe the next time you have a candy bar, you’ll think about World War I. True Treats is open daily. They also have an extensive website if you are craving Goldenberg’s Peanut Chews or some of the other interesting sweets we talked about on today’s show. Listen and subscribe on Apple Podcasts, Spotify, and all major podcast apps. Our podcast is a co-production of Atlas Obscura and Sirius XM Podcasts. This episode was produced by Johanna Mayer. The production team for this episode includes Dylan Thuras, Doug Baldinger, Kameel Stanley, Manolo Morales, Jerome Campbell, Amanda McGowan, Alexa Lim, Casey Holford, and Luz Fleming. Our theme music is by Sam Tyndall.

20.05.2026 16:15:00

Dobrodružství
5 dní

In 1917, German explorer Reinhard Maack discovered a group of rock paintings while surveying Brandberg Mountain in the northwestern Namibian desert.  Forced to take shelter one night in a rocky outcropping, Maack awoke the next morning to find a wall of primitive rock paintings. Believed to be 2,000 years old, the Brandberg paintings were drawn with charcoal, crushed sandstone, animal blood, hematite, manganese, and other natural materials.  Casein and egg white were used as binders.  The decorated rock wall area measures approximately 18 by 5 feet.  Amazingly, and with little protection from the elements, the paintings have survived with only minor fading. Central to the Brandberg panel is a human figure larger than the others, appearing to be a white-skinned woman.  In fact, it is neither.  The figure measures 15.6 by 11.4 inches.  It is believed to depict a shaman or medicine man.  He has white arms and legs, which may indicate body paint or ceremonial attire.  He holds a bow in one hand and a goblet or chalice in the other.  The ornaments on his arms and legs could indicate a ritual dance.  However, the bow and oryxes might imply a hunting scene. Rock painting and drawing were intended as methods of communication among nomadic groups and conveyed practical information, such as hunting success and the location of watering holes.  The Brandberg painting depicts a group of people and animals.  The animals include oryx, zebra, and blue wildebeest.  Some figures seem to be hybrids of animals and humans, such as an oryx with human legs.  These creatures seem to indicate a shaman’s mystical ability to shape-shift.  The painting received no international attention until 1955, when Abbe Henri Breuil copied it.  He entitled his subsequent academic paper and book, “The White Lady of Brandberg,” and the gender appellation stuck.  It was originally thought to be of Mediterranean origin. Still, subsequent analysis suggests the painting is a work of the San people, hunter-gatherers who lived in the area thousands of years ago.  Brandberg Mountain is a significant spiritual site to the San Bushmen.  The location of the rock wall art is now a protected Namibian heritage site.  After decades of wear and tear by tourists, two horizontal metal bars protect the art while permitting complete viewing.

20.05.2026 16:00:00

Dobrodružství
5 dní

Bramall Hall in the Bramhall  district of Stockport , UK, (the difference in spelling is correct and has varied a lot over the centuries) is a typical Tudor timber-framed manor house constructed from timbers held together by mortice and tenon joints secured with wooden pegs. The gaps between the timbers were filled with wattle and daub. Bramall Hall, in its current form, was constructed  by the Davenport family in the 16th century, although the earliest part of the house originated from the 14th century. The manor of Bramhall originated in the 11th century when William the Conqueror seized two adjacent Saxon manors and handed the land to one of his Norman supporters. The hall currently  sits in 50 acres of fine parkland which is open to the public (free of charge). In 1935 the house and park were purchased by the local authority at the time which became part of Stockport Metropolitan Borough Council in 1974.  Its appearance is  similar to Little Moreton Hall, about 20 miles away, but its structure is far more "intact" than Moreton which seems to have suffered from structural subsidence that originated from internal alterations. The house  is set out as a museum with rooms furnished from various dates in the house's history and provides a fascinating glimpse of the life of a house from the 16th to the 20th century. The most impressive room in the house is probably the "Solar" a large reception area which was formed by the joining together of smaller rooms. The house also boasts an interesting selection of of beds ranging from simple beds for the servants to some magnificent four posters with very ornate hangings. There is also a famous Elizabethan embroidered heraldic carpet (17 feet long and 7 feet wide) which, as was custom at that time,  was made to fit on a table. The Hall is fortunate to still retain the table for which it was made. Only 2 similar carpets are known in the world. In 1910 the cultural status of the house was reflected by the fact that the  Lord Lieutenant of Cheshire chose Bramhall Park as the site for the local proclamation of the accession of King George V.

20.05.2026 12:00:00

Domácí

Domácí
dnes

Prezident Petr Pavel je jediným z případných kandidátů na příští hlavu státu, který může dostat víc než polovinu hlasů. Vyplývá to z výsledků průzkumu z přelomu dubna a května, které v pondělí agentura STEM/MARK zveřejnila na webu. Pavla by podle průzkumu volilo nebo možná volilo 53 procent lidí v Česku, následuje premiér Andrej Babiš (ANO) se 44 procenty. Z dalších osobností, které lidem předložila agentura STEM/MARK, by 40 procent dostal herec a moderátor Marek Eben, 35 procent ministr průmyslu a obchodu Karel Havlíček (ANO) a 30 procent ministryně financí Alena Schillerová (ANO). Pavel je zároveň jediným případným kandidátem, kterého odmítá za prezidenta méně než polovina dotázaných.  Lidí, kteří by Pavla prezidentem nevolili, je 45 procent, u Babiše je to 56 procent, u Ebena 53 procent, u Havlíčka 51 procent a u Schillerové 65 procent. Nejodmítanějším v průzkumu nabízeným případným prezidentským kandidátem byl bývalý premiér Petr Fiala (ODS), kterého by do čela Česka nechtělo 80 procent lidí. Následoval poslanec a vládní zmocněnec pro Green Deal Filip Turek (za Motoristy) se 79 procenty, shodně 74 procent dotázaných odmítá za hlavu státu předsedy menších vládních stran Tomia Okamuru (SPD) a Petra Macinku (Motoristé). Před výběrem z nabízených možností nechal STEM/MARK lidi na otázku, kdo by měl být v roce 2028 prezidentem, odpovědět spontánně. Takto dokázalo konkrétní jméno uvést 38 procent potenciálních voličů. "Spektrum jmen, která se objevovala, je poměrně široké. Mezi nejčastěji skloňovanými jmény ale dominoval současný prezident Petr Pavel, s výrazným odstupem pak Andrej Babiš či Karel Havlíček a…

25.05.2026 13:19:32

Domácí
dnes

Ruští vojenští blogeři, kteří dlouhodobě kritizují způsob, jakým Rusko vede takzvanou speciální vojenskou operaci, mají po masivních víkendových úderech na Ukrajinu čerstvý důvod k nespokojenosti. Útoky, při nichž Rusko vyslalo na 600 dronů a 90 raket včetně obávaného Orešniku, kritizují jako zbytečně drahé a vojensky bezvýznamné zakrývání ruských neúspěchů na frontě. O názorech takzvaných turbopatriotů, nacionalistických vojenských blogerů, kteří Vladimiru Putinovi a jeho lidem vyčítají mimo jiné to, že jsou ve válce proti Ukrajině příliš mírní, informoval americký think-tank Institut pro studium války (ISW). Blogeři masivní útok, který v noci na neděli zasáhl především Kyjev a širší okolí, považují za nákladné odvedení pozornosti (cenu tohoto úderu Ukrajinci odhadli na více než 7,5 miliardy korun, pozn. red.) od selhávání na bojišti. Útoky podle nich byly nejen drahé, ale také převážně symbolické, protože nepřispěly k ruskému válečnému úsilí. Blogeři poukázali mimo jiné na to, že Orešnik v Bílé Cerkvi ležící asi 80 kilometrů od Kyjeva neměl jasný vojenský cíl. Je chybou, že zatímco ruské síly nemají dostatek zdrojů a nejsou schopny postupovat na frontové linii, ruské vojenské velení upřednostňuje drahé údery, upozornil jeden z vojenských blogerů. Další argumentoval, že ukrajinské síly úspěšně útočí na ruské logistické cíle na okupované Ukrajině a že ruské údery na Kyjev nebudou schopny Ukrajině zabránit v jejich pokračování. Jak již deník FORUM 24 opakovaně informoval, nespokojenost mezi ruskými válečnými blogery sílí. V poslední době kritizovali zejména neschopnost Ruska chránit před ukrajinskými…

25.05.2026 12:58:06

Domácí
dnes

KOMENTÁŘ / V noci na neděli zažila Ukrajina další masivní ruský útok. Především na hlavní město a Kyjevskou oblast mířili stovky dronů, desítky balistických raket včetně mezikontinentální rakety „Orešnik“, která explodovala ve městě Bila Cerkva. Sociální sítě zaplavili obrázky hořícího Kyjeva a místní úřady hlásí minimálně čtyři mrtvé a desítky zraněných civilistů. Jednalo se o jeden z nejrozsáhlejších útoků na ukrajinskou metropoli od počátku plošné ruské invaze na Ukrajinu v únoru 2022.  A z toho je možné odvodit závěry nejen pro Ukrajinu.    Letošní oslavy výročí vítězství ve druhé světové válce na Rudém náměstí v Moskvě vzbuzovaly zájem především svojí skromností a spíše možností ukrajinského útoku než tradiční pompézností, kterou se takové ruské oslavy vždy pyšnilyy. Zaujal také projev ruského prezidenta Vladimíra Putina. A to nejen tradiční ostrou militantní rétorikou, ale dosti nečekaným tvrzením, že se válka proti Ukrajině „blíží ke konci“. V Putinově případě sice nelze odhadnout, jak přesně si představuje „konec války“ a jak dlouho z časového hlediska může ještě ruská agrese proti Ukrajině pokračovat. Zda má na mysli týdny, nebo roky není zcela jasné. Agonie, nebo demonstrace síly? Zdá se ale, že se jedná o jistý signál, kterého se chopili západní analytici a pozorovatelé. Americký portál Bloomberg přišel s informacemi od zdrojů blízkých Kremlu, že Putin by chtěl válku ukončit do konce letošního roku. Ale podle vlastních představ. Ukrajina by měla ustoupit z těch území na Donbase, která jsou stále pod kontrolou Kyjeva a jež se Rusku nedaří obsadit již víc než deset let. Tento zisk by pak měl být formálně zajištěn nějakou formou dohody se Západem.

25.05.2026 12:57:26

Domácí
dnes

Velice tvrdě se vyjádřil ukrajinský velvyslanec v České republice Vasyl Zvaryč na adresu Ruské federace po posledním masivním vzdušném útoku na svou zemi. „Žádný takový teroristický útok nezlomí ducha Ukrajinců, ale naopak přiblíží pád ruské hordy,“ řekl oblečený do trička s nápisem „Fuck you, Putin“ „Přesně taková je moje odpověď, odpověď ukrajinských diplomatů a všech Ukrajinců na dnešní noční barbarské útoky Ruska proti Ukrajině, které zasáhly Ministerstvo zahraničních věcí a budovu vlády Ukrajiny,“ řekl Zvaryč ve svém příspěvku na sociální síti X. Žádný takový teroristický útok Ruska nezlomí ducha Ukrajinců, ale naopak přiblíží pád ruské hordy. A „ура“ vám nepomůže.Sláva Ukrajině! Sláva Hrdinům! 🇺🇦🇺🇦🇺🇦✌️#RussiaIsATerroristState #StopRussianAggression #StandWithUkraine️ pic.twitter.com/wqoEHahPnn— Vasyl Zvarych (@Vasyl_Zvarych) May 24, 2026 „Žádný takový teroristický útok nezlomí ducha Ukrajinců, ale naopak přiblíží pád ruské hordy. A ,urá´ vám nepomůže. Sláva Ukrajině!“ dodal. Ukrajinský velvyslanec si při té příležitosti oblékl tričko české organizace Dárek pro Putina, které slouží pro podporu napadené země. Tričko navrhl slovenský designér Dodo Dobrík jako bezprostřední reakci na zločiny ruské armády v ukrajinském Izjumu, popsala organizace. Ukrajinský velvyslanec reagoval na masivní kombinovaný ruský vzdušný útok, k němuž došlo v noci na 24. května. Na Ukrajinu zamířilo více než 600 dronů a desítky raket, včetně balistické rakety středního doletu „Orešnik“. Střely zasáhly centrum Kyjeva, obytné domy, nákupní centrum a další civilní cíle. Podle Ukrajiny útok směřoval především proti civilistům, aby zastrašil Ukrajince pokračující v útocích proti ruské energetické infrastruktuře, přístavům a průmyslovým podnikům podporujícím ruskou válečnou agresi na Ukrajině.

25.05.2026 12:55:27

Domácí
dnes

NÁZOR / Jaroslav Foldyna je politik, který se v průběhu své kariéry pohyboval od sociální demokracie k SPD Tomia Okamury. To je dráha,  na které se skutečně nemuselo spotřebovat mnoho intelektuálního paliva. Foldynovi stačilo, že je výrazný řečník, takzvaně lidový. Když píše, dělá to tak, jak mluví. Aspoň do neděle to tak dělal. Minulý týden zveřejnil na svém facebookovém profilu příspěvek k sjezdu Sudetoněmeckého landsmanšaftu v Brně. Hned zaujme, že je nezvykle dlouhý, asi necelých šest set slov. Většinou pan poslanec vyniká stručností. „Ženíšek jen dokazuje jaký je blb!“ napsal třeba 1. května. (Chybí mu tam čárka.) Dost nezvykle zní třeba tohle: "Proto vás teď žádám a prosím: přestaňte otevírat staré rány. Přestaňte provokovat návrat starých konfliktů. Rozpusťte Landsmanšaft a přestaňte sloužit lidem, kteří vás používají jen jako nástroj obecného rozvratu a vlastního obohacení. Prosím vás: seberte se a — pro lásku Boží — jeďte domů." Foldyna prosí a zaklíná se Boží láskou. Pozoruhodné. Tématicky text začíná, jak bývá obvyklé. Je tu připomínka, že Henleinovu nacistickou stranu před válkou podporovalo přibližně 90 procent sudetských Němců. Pak ale přijde něco, co Foldyna prostě neumí napsat. „To, co se dnes odehrává, je další dílek velké skládačky. Skládačky, jejímž výsledkem má být rozklad naší civilizace — civilizace křesťanské, evropské, a tedy i německé." Takhle Foldyn nemluví a nepíše a zarazí i ta dlouhá pomlčka. Prostě se nám vloudí podezření, jestli si pan poslanec trochu nepomohl použitím umělé inteligence, nebo nějak jinak. V takovém případě je dobré se také obrátit na…

25.05.2026 12:52:38

Domácí
dnes

Desítky lidí se v pondělí dopoledne sešly před úřadem vlády k dalšímu protestu proti rušení poplatků České televizi a Českému rozhlasu. Akci uspořádal spolek Milion chvilek, který organizoval shromáždění a následný pochod na podporu veřejnoprávních médií ze Staroměstského náměstí ke Strakově akademii i v neděli odpoledne. „Oto, zabal to!“ skandovali v narážce na ministra kultury Oto Klempíře (za Motoristy) demonstranti před budovou, kde jedná kabinet Andreje Babiše (ANO). Předseda spolku Mikuláš Minář na začátku shromáždění poděkoval lidem, že přišli protestovat před vládu i dnes, kdy je mohou slyšet a vidět i členové kabinetu. Řečníci i účastníci protestu skandováním "Hanba" či s transparenty kritizovali zákon, který má zavést financování veřejnoprávní televize a rozhlasu ze státního rozpočtu místo současného systému poplatků od občanů a firem. Požadovali také odstoupení ministra kultury Oty Klempíře, který zákon připravuje. Klempířův odchod žádá i nová petice, kterou Milion chvilek inicioval. Na protest dorazil i bývalý šéf Pirátů a někdejší ministr pro místní rozvoj Ivan Bartoš. Také on dorazil vybaven transparentem "Oto, zabal to!". "Vláda chce mít televizi za naše peníze pro jejich propagandu," prohlásil pak na pondělní demonstraci před Úřadem vlády písničkář Zbyněk Ziggy Horváth. Návrhem se má v pondělí večer zabývat koaliční rada, teprve po dohodě mezi zástupci ANO, SPD a Motoristy ho dostane k projednání vláda. K návrhu ministerstva kultury přišlo přes 300 připomínek obou médií, komerčního sektoru, ministerstva financí, vnitra a dalších resortů. Milion chvilek tvrdí, že předloha povede ke zestátnění veřejnoprávních médií. Návrh označuje za "zfušovaný, nebezpečný a neopravitelný paskvil". Milion chvilek…

25.05.2026 12:10:38

Domácí
dnes

Výrok ministra zahraničí Petra Macinky (Motoristé) o přijetí bavorského premiéra Markuse Södera prezidentem Petrem Pavlem vyvolal ostré reakce. Kritika se netýká jen samotného nesouhlasu s prezidentovým krokem, ale především způsobu, jakým Macinka kritiku formuloval. Jako první zareagoval místopředseda TOP 09 Marek Ženíšek. „Petr Macinka kritizoval prezidenta Petra Pavla za to, že přijme bavorského premiéra Markuse Södera,” napsal na síti X. A dodal: „Tady pro vás něco mám, ostudo.“ Ke svému příspěvku připojil fotografii premiéra Andreje Babiše, jak si s úsměvem podává ruku – ano, právě s bavorským premiérem Markusem Söderem. Ve skutečnosti ale nejde jen o politickou kritiku prezidenta. Podstatné je, jakým způsobem Macinka, který vede s prezidentem osobní spor kvůli nejmenování Filipa Turka do ministerské funkce, svůj postoj vyjádřil.  https://x.com/zenisek_m/status/2058555782753341552?s=46 Jako host prvního vysílání internetového projektu Václava Moravce dostal ministr zahraničí otázku moderátora: „Považujete za zásadní chybu, že prezident odpoledne přijme bavorského premiéra?“ Macinka odpověděl: „No, tak nevím, jestli zásadní. Já bych to asi nedělal zrovna u této příležitosti a v tento den.” Prezident Petr Pavel přijal bavorského premiéra Markuse Södera na Pražském hradě v neděli. Jednání trvalo přibližně půl hodiny. Söder se předtím zúčastnil sjezdu Sudetoněmeckého krajanského sdružení v Brně, který označil za slavnost míru. Macinka však pokračoval ještě ostřeji. K návštěvě Södera dodal: „Navíc to není jako jeho váhová kategorie. Prostě to je tak váhová kategorie třeba plzeňského nebo karlovarského hejtmana.” Tato slova nadzvedla politického glosátora Jiřího Lobkowicze. „Petr Macinka předvedl až děsivou kombinaci ignorance a arogance,” napsal na síti X. A pokračoval: „Srovnávat setkání českého prezidenta…

25.05.2026 11:37:31

Domácí
dnes

Sjezd sudetských Němců by se mohl v budoucnu konat střídavě v Bavorsku a v Česku. Bavorské veřejnoprávní stanici BR to na sjezdu v Brně řekl předák sudetských Němců Bernd Posselt. V řadě českých měst už podle něj místní projevili o pořádání sjezdu zájem. Setkání v Brně dnes po čtyřech dnech končí uctěním památky obětí nacismu. Podle německého listu Süddeutsche Zeitung byla celková atmosféra sjezdu navzdory protestům pokojná a nálada srdečná. V příštím roce se podle Posselta sjezd sudetských Němců uskuteční opět v Německu, a to v Norimberku. O pořádání některého z příštích sjezdů podle něj ale usiluje "několik českých měst". Jako příklad uvedl Cheb, kde podle něj příslušnou občanskou iniciativu vede bývalý starosta města Antonín Jalovec. "Dokázal bych si představit, že v budoucnu se Sudetoněmecký sněm bude konat střídavě v Bavorsku a v České republice," dodal Posselt. Sjezd v Brně označil nejvyšší představitel sudetských Němců za "skvělý" a za "jednu velkou oslavu přátelství a smíření". Posselt ocenil otevřenou debatu o společné kultuře a dějinách Čechů a sudetských Němců, ale i "o strašlivých zločinech nacistů a o zločinu vyhnání". "Myslím si, že tato široká debata měla velký terapeutický význam," dodal. Za osobní vrchol sjezdu pak Posselt v rozhovoru s BR označil čtvrteční pietu za oběti holokaustu na brněnském hlavním nádraží, na kterém se setkal s Evou Paddockovou a Milenou Grenfell-Bainesovou. Obě patří k dětem, které před hrůzami holokaustu zachránil Nicholas Winton. "Jedna z nich mi řekla, že přijela jen proto, aby mi potřásla rukou. To mě rozplakalo,"…

25.05.2026 11:31:09

Domácí
dnes

Do jedné z nemocnic ve východním Kongu, kde leží pacienti s ebolou, vtrhli v neděli večer ozbrojení mladí muži. Následně po personálu žádali, aby jim byla předána těla jejich příbuzných. Africkou zemí v současné době otřásá právě epidemie eboly. Často zde vyvolává nepokoje fakt, že pozůstalí nemohou pohřbít těla svých příbuzných, jelikož vir je i po smrti pacienta vysoce nakažlivý. Ozbrojení mladí muži vtrhli v neděli do nemocnice v Mongwalu ve východní části Konga a následně začali střílet. Podle agentury AP museli zaměstnanci nemocnice pacienty rychle evakuovat. Do této chvíle prý není jasné, zdali má střelba nějaké oběti či jestli je někdo zraněný. Ředitel nemocnice sdělil, že ozbrojenci žádali těla dvou svých příbuzných, kteří podlehli nákaze ebolou. Právě epidemie této nemoci nyní otřásá africkou zemí. „Všeobecná nemocnice Mongbwalu je v pohotovosti,“ vzkázal. Jedná se již o třetí útok na nemocnici v Kongu za poslední týden. Často prý vyvolává nepokoje skutečnost, že že pozůstalí nemohou pohřbít těla svých příbuzných. Vir je totiž i po smrti nakažených stále vysoce nakažlivý. V sobotu například zapálila skupina lidí stan Lékařů bez hranic s pacienty, kteří se buď dostali do kontaktu s ebolou, nebo už jsou nakažení. Bylo zde totiž i tělo jedné z obětí, které lékaři odmítli pozůstalým vydat. Po zmíněném požárů zůstává 18 nakažených osob mezi nezvěstnými.

25.05.2026 11:25:29

Domácí
dnes

Francouzský prezident Emmanuel Macron varoval svůj běloruský protějšek Alexandra Lukašenka před zapojením Běloruska do válečného konfliktu na Ukrajině. Macron v telefonátu zdůraznil rizika, která by Bělorusku hrozila, pokud by se do války nechalo zatáhnout. Macron pak Lukašenka rovněž vyzval k tomu, aby podnikl nezbytné kroky ke zlepšení vztahů mezi Běloruskem a Evropskou unií (EU). Emanuel Macron během nedělního telefonátu s Alexandrem Lukašenkem zdůraznil možná rizika, která by Bělorusku hrozila, pokud by i nadále posilovalo svou roli v rámci válečného konfliktu mezi Ukrajinou a Ruskem. Reagoval tak na sílící obavy z otevření další ruské útočné linie právě z běloruského území. Jednalo se o první přímý kontakt mezi oběma prezidenty od začátku války na Ukrajině v roce 2022. „Macron zdůraznil rizika pro Bělorusko, pokud se nechá zatáhnout do agresivní války Ruska proti Ukrajině. Vyzval také Alexandra Lukašenka, aby podnikl nezbytné kroky ke zlepšení vztahů mezi Běloruskem a Evropou,“ informovala agentura AFP. Francouzský prezident inicioval rozhovor po rozsáhlém ruském útoku na Kyjev, který Macron jednoznačně odsoudil. Minsk a Moskva podepsaly v květnu 2023  dokumenty ohledně rozmístění ruských taktických jaderných zbraní v Bělorusku. První hlavice tam Rusko dopravilo téhož roku. Minulý týden nacvičovali ruští a běloruští vojáci při společném cvičení, do kterého se zapojily také ruské strategické síly, použití jaderných zbraní, což vyvolalo obavy. Během začátku války na Ukrajině také Lukašenko, jenž je považován za nejbližšího spojence Kremlu, poskytl Rusku běloruské území pro svůj útok na sousední zemi. Z ruských leteckých základen v Bělorusku také startovaly ruské letouny při bombardování ukrajinských měst a obcí. Také…

25.05.2026 11:03:16

Domácí
dnes

Tři tisíce rodinných domů. Patnáct až třicet základních škol, anebo krajská nemocnice by se daly postavit za cenu raket a dronů, které Ruská federace vyslala o víkendu na Ukrajinu. Suma, kterou za poslední velký vzdušný úder Rusové zaplatili, byla astronomická. Masivní letecký úder na Ukrajinu, k němuž došlo 24. května, způsobil značné škody na ukrajinské civilní infrastruktuře. Značně drahý byl však také pro Rusy, popsal ukrajinský deník Armija Inform, který sečetl cenu použitých zbraní na základě informací dostupných z otevřených zdrojů. Vycházel z toho, že Rusové během úderu použili na 90 raket a 600 bezpilotních letounů různých typů. Byla mezi nimi ruská balistická raketa středního doletu Orešnik v hodnotě 50 milionů dolarů (1 miliarda korun), dvě ruská hypersonické balistické rakety Ch-47M2 Kinžal, v hodnotě 10 milionů dolarů (208 milionů korun), tři protilodní střely 3M22 Zirkon v hodnotě 16,2 milionu dolarů (337 milionů korun), 30 balistických raket Iskander-M, 54 dalších střel a šest set útočných bezpilotních letounů. Ruský útok, který mířil takřka výhradně na civilní infrastrukturu a obytné budovy, neměl přitom valný vojenský význam. Jeho cílem bylo podle Ukrajinců zastrašit Ukrajince po úspěšných úderech, které jejich ozbrojené síly provedly v ruském vnitrozemí. Cena tohoto úderu podle Ukrajinců v součtu činila 361,2 milionu dolarů, tedy více než 7,5 miliardy korun. „Jedná se o roční rozpočty desítek malých měst, nebo stovek vesnic v Rusku,“ popsali Ukrajinci s tím, že Rusové si stěžují na špatný stav nemocnic, silnic a městské infrastruktury, zatímco Kreml vyhodil stovky milionů dolarů za jedinou…

25.05.2026 10:55:31

Domácí
dnes

Mezi ruskými elitami sílí rozčarování z ruského prezidenta Vladimira Putina. Důvodem je vleklá válka proti Ukrajině, rostoucí ekonomické problémy i stále tvrdší represe uvnitř země. Tvrdí to britský deník The Guardian, který se odvolává na rozhovory s lidmi z okolí Kremlu, podnikatelského prostředí i západních tajných služeb. „Letos mezi elitami rozhodně došlo ke změně nálady… Putin je hluboce zklamal,“ citoval deník dobře informovaného ruského podnikatele. Podle něj navíc v ruských mocenských kruzích „roste pocit, že se blíží nějaká katastrofa“. The Guardian popisuje Putina jako stále izolovanějšího vůdce, kolem něhož přibývá lidí ztrácejících víru v další vývoj země. Další zdroj uvedl, že lidé, kteří dříve Putina obhajovali, od něj dávají ruce pryč. „Nikdo nevěří, že se zítra všechno náhle zhroutí. Ale stále více si uvědomujeme, že se dál dělají naprosto nesmyslná, sebedestruktivní rozhodnutí. Lidé, kteří kdysi Putina bránili, už to nedělají. Jakýkoli pocit budoucnosti zmizel,“ citoval The Guardian člověka obeznámeného se současnou situací uvnitř Ruska. Navzdory rostoucí nervozitě uvnitř Ruska se postoj Kremlu k válce podle zdrojů nemění. Putin je údajně přesvědčen, že ruská armáda dokáže do konce roku obsadit celý Donbas. „Putin je fixovaný na Donbas a nezastaví se dřív,“ uvedl dle Britů další zdroj s přístupem k ruskému prezidentovi. Dalším faktorem ovlivňujícím situaci je podle The Guardian také vývoj ve Spojených státech. Moskva podle zdrojů původně věřila, že by americký prezident Donald Trump mohl po svém návratu do funkce vyvinout tlak na Kyjev, aby se vzdal části území. Tato očekávání ale údajně slábnou. „V Moskvě…

25.05.2026 10:49:37

Domácí
dnes

Současná bezpečnostní situace je nejvážnější a nejsložitější od studené války a Evropa čelí kombinaci velkých ozbrojených konfliktů, hybridních hrozeb i proměny globální rovnováhy sil. Na konferenci Aktuální bezpečnostní hrozby to řekl náčelník generálního štábu Karel Řehka. Zdůraznil ale, že situace je zvládnutelná, pokud budou státy jednat včas a důsledně. "Nemám pochybnost o tom, že žijeme v době, kdy je bezpečnostní situace nejkomplexnější a nejsložitější od studené války. Nemám pochybnost, že situace může v nejhorším případě vyústit v něco, co by byla tragédie pro Českou republiku. Ale nemám pochybnost, že je to zvládnutelné. Záleží to jen na nás," uvedl Řehka. Řehka řekl, že současné konflikty na Ukrajině a Blízkém východě zásadně mění charakter válčení a přinášejí přímé i nepřímé dopady pro Českou republiku, které by se podle Řehky měly promítat do české i evropské bezpečnostně-zahraniční politiky. "Absence urgence pro nás může být fatální a mám obavy, že přes všechnu rétoriku tak skrz reálné skutky máme absenci té urgence," dodal. Případný mír na Ukrajině neznamená podle Řehky konec ruské hrozby. "Rusko nebude přátelštější a vybralo si strategii, kdy směřuje více ke střetu se Západem," řekl. Podle něj je proto potřeba budovat silný systém odstrašení a obrany, který omezí riziko chybné kalkulace Moskvy, jako když se rozhodla pro plnohodnotnou invazi na Ukrajinu. Zdůraznil také význam pokračující podpory Ukrajiny. Podpora Kyjeva podle něj není altruismem ani charitou, ale strategickým zájmem České republiky. Za klíčové Řehka označil mimo jiné modernizaci armády, posilování ochrany kritické infrastruktury, investic do personálu, budování celospolečenské odolnosti, ale také plnění dohodnutých…

25.05.2026 10:48:07

Domácí
dnes

Nejzoufalejší argument je argument opírající se o vzhled, vpálil exministr vnitra a šéf hnutí STAN Vít Rakušan bývalé poslankyni za hnutí ANO Marcele Melkové, která na sociální síti urážela šéfa Sudetoněmeckého krajanského sdružení (SdL) Bernda Posselta kvůli jeho vzhledu. Rakušan ve své reakci Melkové připomněl, že takovým způsobem se chovali nacisté. „Ano ano, tu lásku má pan Posselt přímo vepsanou ve tváři,“ navezla se sprostě do šéfa Sudetoněmeckého krajanského sdružení někdejší poslankyně a členka hnutí ANO Melková. Na sociální síti tak komentovala Posseltův nedělní projev k účastníkům sudetoněmeckého sjezdu, ve kterém prohlásil, že sudetští Němci do Brna přijeli s poselstvím lásky, a nikoli nenávisti. Urážky ze strany Melkové nenechaly chladným předsedu opozičních Starostů Rakušana. „Nejpovrchnější, nejhloupější a nejzoufalejší argument je argument opírající se o vzhled,“ vypálil na adresu členky Babišovy partaje. „Víte, kdo třídil lidi podle toho, jestli měli dost blond vlasy, odpovídající tvar lebky nebo hezky zakulacené uši?“ vzkázal Melkové v narážce na norimberské zákony přijaté nacistickým Německem v roce 1935, které zavedly právní nerovnost Židů, vyloučily je z německé společnosti a staly se klíčovým krokem vedoucím k holokaustu. Komunisté nás chtějí poučovat, co je svoboda  Posselt ve svém nedělním proslovu k účastníkům sudetoněmeckého sjezdu v Brně hovořil také o složité cestě usmiřování a o odvaze těch českých osobností, které se z české strany k hledání společného přátelství vydaly jako první. „Nebylo to samozřejmé,“ prohlásil šéf Sudetoněmeckého krajanského sdružení. Krátce se vyjádřil také k protestům proti sjezdu…

25.05.2026 10:45:11

Domácí
dnes

Lednové zadržení člověka, který je podezřelý z činnosti pro čínskou zpravodajskou službu, ukazuje podle šéfa Bezpečnostní informační služby (BIS) Michala Koudelky schopnost zasahovat proti protivníkům, ale má i symbolický význam. K takovému odhalení a následnému trestněprávnímu řešení se odhodlá jen hrstka zemí ve světě a v tomto exkluzivním klubu je nyní i Česko, řekl Koudelka na pondělní bezpečnostní konferenci ve Sněmovně. Čínského občana zadrželi kriminalisté v lednu, obvinili ho z trestného činu neoprávněné činnosti pro cizí moc. Je prvním stíhaným za tento paragraf v České republice. Od svého zadržení je ve vazbě, policie navrhla jeho obžalobu. „Česká republika ukázala Číňanům to, co už vědí Rusové, a to, že si u nás nemohou dělat, co chtějí. Že jsme hrdou zemí, ve které platí právo a zákon. A já jsem velmi rád, že k tomu naše služba zásadním způsobem přispívá,“ řekl šéf kontrarozvědky. Koudelka uvedl, že identifikace příslušníka čínské zpravodajské služby MSS pod novinářským krytím byla výsledkem operace BIS. „Tento případ nejen ukazuje naši schopnost zasahovat proti protivníkům, ale má i symbolický význam, protože k takovémuto odhalení a následnému trestněprávnímu řešení se odhodlá jen několik málo zemí ve světě. Spojené státy, Velká Británie, Francie a hrstka dalších,“ dodal. Server Seznam Zprávy napsal, že obviněný je pražským zpravodajem čínského deníku, jenž je stranickým médiem čínské komunistické strany. V Česku podle webu působil roky, česká vláda mu opakovaně prodlužovala akreditaci. Dělal rozhovory s českými a slovenskými politiky, od kterých se podle bezpečnostních složek pokoušel sbírat informace. Podle dalších informací médií…

25.05.2026 10:30:51

Domácí
dnes

Premiér Andrej Babiš (ANO) vyvolal svými úvahami o prodeji státního výrobce výbušnin a střeliva Explosia vlnu ostré kritiky. Do premiéra se vedle opozice opřela i vládní poslankyně ze strany SPD Marie Pošarová. Prodej strategického podniku, kterému se ekonomicky extrémně daří, přirovnala k nesmyslnému chování sedláka a Babišovi doporučila „klobouček proti úpalu“. Úvahy o prodeji pardubické Explosie zveřejnil premiér Andrej Babiš v pátek s tím, že o firmu projevila zájem Francie prostřednictvím prezidenta Emmanuela Macrona a také další evropské i české společnosti. Hlavním motivem má být extrémně vysoký výnos, který by stát mohl využít například na splnění závazků vůči NATO v oblasti obranných výdajů. Podle Babiše je jediným kritériem cena. „Těžký úpal pana premiéra“ „A já se ptám, proč to chce prodat? Protože z ekonomického ani bezpečnostního hlediska to nedává smysl. To je jako kdyby sedlák chtěl prodat slepici, která mu snáší zlatá vejce a chtěl si pořídit nový kurník,“ uvedla Pošarová ve videu na sociálních sítích. Premiérovi zároveň vzkázala, že jeho uvažování působí jako následek zdravotních indispozic z horka. „Panu premiérovi doporučuji nosit klobouček, protože to vypadá na těžký úpal,“ dodala poslankyně. https://x.com/Posledniskaut/status/2058657240236605660?s=20 Nebezpečný nápad, varuje opozice Kritika však nezní pouze z řad SPD. Bývalá ministryně obrany Jana Černochová (ODS) označila nápad za nekompetentní a nebezpečný, zejména v době, kdy se celý svět snaží posilovat vlastní obranný průmysl a nezávislost na cizích dodavatelích. Podle ní stát, který se zbavuje klíčové výroby v oblasti obrany, oslabuje sám sebe. Podobně se vyjádřili i další politici. Lukáš…

25.05.2026 10:28:42

Domácí
dnes

Nejvyšší kontrolní úřad (NKÚ) upozornil na problémy při využívání evropských dotací určených na posílení odolnosti českých nemocnic po pandemii covidu-19. Kontrola zaměřená na ministerstva zdravotnictví a pro místní rozvoj i vybrané nemocnice ukázala, že část prostředků nebyla využita účelně a efektivně. Některé nemocnice podle kontrolorů pořizovaly přístroje, které následně využívaly jen minimálně, případně pro ně neměly dostatek kvalifikovaného personálu. Česká republika získala v letech 2020 až 2023 téměř 19 miliard korun z evropského investičního nástroje REACT-EU, který měl pomoci se zotavením po pandemii covidu-19. Vláda rozhodla, že většina těchto prostředků bude směřovat do zdravotnictví, konkrétně na posílení připravenosti nemocnic na budoucí krizové situace. Podle NKÚ však ministerstva dostatečně neověřovala skutečnou potřebnost pořizovaných přístrojů. „NKÚ prověřil nákup 27 přístrojů. Dvanáct z nich v celkové pořizovací hodnotě 41,1 milionu korun nemocnice používaly významně méně, než bylo běžné u obdobných přístrojů v ČR,“ konstatoval NKÚ. Kontroloři upozornili také na časový tlak spojený s čerpáním dotací. Prostředky musely být vyčerpány během necelých tří let, což podle NKÚ vedlo k tomu, že ministerstva upřednostnila rychlé nákupy přístrojů a vybavení před dlouhodobějšími investicemi, které by mohly výrazněji posílit schopnost zdravotnictví zvládat mimořádné situace. Dotace navíc pokrývaly sto procent nákladů, takže některé nemocnice pořizovaly vybavení i jako záložní. Ministerstvo pro místní rozvoj s kritikou NKÚ nesouhlasí. Podle jeho mluvčí Veroniky Lukášové bylo hlavním cílem dotací zajistit nemocnicím schopnost pružně reagovat na budoucí pandemie a další krizové situace. Ministerstvo zároveň zdůraznilo, že v době pandemie nebylo možné přesně předvídat, jaké typy přístrojů budou nemocnice v budoucnu potřebovat. Ministerstvo zdravotnictví proto vytvořilo…

25.05.2026 09:23:11

Domácí
dnes

Spojené státy buď dosáhnou s Íránem dobré dohody, nebo se s touto zemí vypořádají jiným způsobem. Řekl to v pondělí podle agentury Reuters novinářům během své návštěvy v Dillí americký ministr zahraničí Marco Rubio. USA podle něj chtějí dát všechny šance diplomacii, než začnou zkoumat alternativní možnosti. Podle agentury AFP Rubio zdůraznil, že Izrael bude mít vždy právo se bránit, ať bude dohoda mezi Washingtonem a Teheránem jakákoli. USA a Izrael na konci února rozpoutaly válku proti Íránu, Teherán odpověděl útoky na země na Blízkém východě a americké základny v regionu. Od 8. dubna platí příměří. Zároveň probíhají jednání o předběžné dohodě, která mají umožnit budoucí konečnou dohodu o míru. Podle zdrojů serveru Axios by předběžná dohoda měla umožnit znovuotevření Hormuzského průlivu a povolit Íránu neomezeně vyvážet ropu. Zároveň by pokračovala jednání o íránském jaderném programu. "Na stole je docela solidní věc, pokud jde o jejich schopnost otevřít (Hormuzský) průliv, otevřít ho, zahájit velmi reálná, významná a časově omezená jednání o jaderné otázce, a doufejme, že to dokážeme," řekl Rubio. Americký prezident Donald Trump v neděli prohlásil, že vyjednávání s Íránem postupuje řádně a konstruktivně, zároveň ale prý americkým vyjednavačům řekl, aby s dohodou nespěchali. Námořní blokáda Íránu podle Trumpa zůstane v plné platnosti, dokud nebude dohoda potvrzena a podepsána. Zároveň slíbil otevření Hormuzského průlivu, který je klíčovou námořní trasou pro přepravu ropy a zemního plynu. Šéf americké diplomacie v pondělí také prohlásil, že Izrael bude mít vždy právo se bránit bez ohledu na jakoukoli dohodu mezi Washingtonem a Teheránem,…

25.05.2026 07:32:38

Domácí
dnes

Koaliční rada by se na pondělním jednání měla zabývat návrhem zákona o médiích veřejné služby. K návrhu ministerstva kultury přišlo přes 300 připomínek od České televize (ČT), Českého rozhlasu (ČRo), komerčního sektoru, ale i ministerstva financí, vnitra a dalších resortů. Po dohodě v koalici předlohu dostane k projednání vláda. Podle dřívějších informací premiéra Andreje Babiše (ANO) by měla vzniknout pracovní skupina za účasti generálních ředitelů obou veřejnoprávních firem. Ministr kultury Oto Klempíř (za Motoristy) minulý týden slíbil v řádu dnů předložení analýzy dopadů zákona, tzv. zprávu RIA. Dosud ji ale nezveřejnil. Podle předlohy by ČT a ČRo měly místo poplatků od domácností a firem dostávat pevnou částku ze státního rozpočtu. ČT by tak příští rok podle záměru měla hospodařit s 5,74 miliardy korun, letos má 8,5 miliardy korun. ČRo by měl od státu získat 2,07 miliardy korun, tedy o 400 milionů méně než letos z poplatků. Záměr kritizují odborníci, opozice i vedení obou médií. Mluví o zestátnění a omezení nezávislosti i dalším zadlužování státu. Pracovníci ČT a ČRo vstoupili 22. dubna do stávkové pohotovosti. Žádají vládu, aby od záměru upustila. Jedním z nejslabších míst předlohy je podle ČT i ČRo vymezení veřejné služby. Ministerstvo financí upozornilo, že návrh neřeší, z jaké rozpočtové kapitoly by Česká televize a Český rozhlas měly dostávat peníze a také termíny jejich výplaty. Zásadní připomínky k návrhu vzneslo dříve i ministerstvo vnitra. Upozornilo, že zrušení koncesionářských poplatků způsobí výpadek příjmů České pošty v objemu 275 milionů korun ročně. Česká pošta výběr poplatků zajišťuje. Opozice se…

25.05.2026 06:54:12

Informační Technologie

Informační Technologie
dnes

mod_wsgi 6.0.0 is currently available as a release candidate. You can install it from PyPI, or grab the source from the GitHub releases page. There is a significant amount of code cleanup behind this release, alongside a range of new features and operator-facing improvements that have been overdue for some time. Rather than describe everything in one post, I am going to work through the headline changes in a short series. The most consequential set for anyone running mod_wsgi in production is the new concurrency configuration. CPython has gained two genuinely new concurrency modes over the last few releases (per-interpreter GIL in 3.12 and free-threading in 3.13), and mod_wsgi 6.0.0 exposes both as opt-in directives, along with finer-grained control over how the GIL switches between threads. This first post covers the per-interpreter GIL story and the new WSGIPerInterpreterGIL directive. Why the GIL has always been the deployment problem This is well-trodden ground, but worth recapping for context. CPython's Global Interpreter Lock serialises Python bytecode execution within a single process. It does not matter how many OS threads you create inside that process. Only one of them runs Python at a time. For WSGI deployments, this has shaped the way servers like mod_wsgi scale. Threads within a single process are useful for handling I/O concurrently, since any reasonable C extension or built-in I/O call releases the GIL while it waits on the kernel, but they do not give you parallelism for CPU-bound Python work. To get that, you have always needed more processes. mod_wsgi's daemon mode is built around this assumption. You configure N daemon processes, each with its own Python interpreter and its own GIL, and you get N-way Python parallelism that way. Sub-interpreters complicate the picture slightly. They have existed in CPython for a long time, and mod_wsgi has used them since the beginning, but until PEP 684 landed in Python 3.12 they all shared one process-wide GIL. Adding more sub-interpreters inside a single process gave you isolation between applications, but no additional concurrency. What changed in Python 3.12 and 3.14 PEP 684 made per-interpreter GIL possible as an opt-in for sub-interpreters created through the C API. With it, each sub-interpreter holds its own lock, and two sub-interpreters running on different OS threads can execute Python bytecode at the same time. The main interpreter is excluded from this. It always holds the original process-wide GIL and cannot be given one of its own. That distinction matters later. Python 3.14 then shipped PEP 734 as concurrent.interpreters, the first standard-library API for working with sub-interpreters from Python code. It is a useful addition, but it does come with a deliberate restriction. Data passed between interpreters is either pickled and copied through a queue, shared through the buffer protocol, or limited to a small set of immortal immutable built-ins. Anything that wants to share mutable Python objects across interpreters has to find another way. That data-sharing restriction is why concurrent.interpreters is most naturally suited to message-passing worker patterns rather than ordinary Python code which tends to lean heavily on shared mutable state. The same restriction is one of the reasons embedding hosts like mod_wsgi are well-positioned to get value out of per-interpreter GIL ahead of general Python code. How mod_wsgi has always used sub-interpreters mod_wsgi has used sub-interpreters from the start, but originally for a completely different reason. The driver was isolation, not parallelism. Running multiple WSGI applications inside a single Apache process is a real operational need, and you cannot do it safely if they all share the same sys.modules, signal handlers, atexit handlers, and so on. Sub-interpreters give each application its own private copy of all of that. mod_wsgi calls this an "application group". Each named application group maps to a sub-interpreter inside whichever daemon process (or embedded Apache child process) is hosting it. Until Python 3.12, that arrangement was purely about keeping applications from stepping on each other. What changes with per-interpreter GIL is that the same sub-interpreters mod_wsgi was already creating for isolation can now hold their own locks and run Python bytecode in parallel. The application group concept does not need to change. The directive that flips this on is new, but the underlying structure is the one mod_wsgi has had all along. There is also a happy alignment with the data-sharing constraint mentioned above. mod_wsgi routes each incoming WSGI request directly into a chosen sub-interpreter, and the WSGI contract does not ask for any shared mutable Python state to span requests. The request is the message. From an application author's point of view, there is not much new to do. The configuration changes; in most cases the application does not. The caveats, and there are always caveats, are what your C extensions will tolerate and, if your application spawns its own background threads, what their shutdown handling looks like under per-interpreter rules. More on both at the end. The new directive The new directive is WSGIPerInterpreterGIL, with the obvious syntax: WSGIPerInterpreterGIL On The default is Off. Opt-in is deliberate; there is no scenario where it would be safe for mod_wsgi to flip this on by default. The directive is valid at server config scope and can also appear inside a <WSGIInterpreterOptions> container, which is what you want most of the time and which I will get to next. Two things worth flagging up front. First, the main interpreter is excluded. If your application runs in the main interpreter, which it will if you have set WSGIApplicationGroup %{GLOBAL}, then enabling WSGIPerInterpreterGIL has no effect on it. Per-interpreter GIL only applies to sub-interpreters. Second, Python 3.12 or later is required. On older Python the directive is accepted but does nothing, with a configuration warning logged. Composing with daemon mode The interesting case for WSGIPerInterpreterGIL is not opting an entire daemon process group into it. If you want extra parallel Python execution across separate processes, you can already get that by adding more daemon processes. The interesting case is selectively enabling per-interpreter GIL for specific sub-interpreters that already exist within a daemon process you are running. A small example. Suppose you have a daemon process group called localhost:8000 running a single WSGI application. You can create a named sub-interpreter inside that process and give it its own GIL, like this: <WSGIInterpreterOptions process-group="localhost:8000" application-group="sub-interp-1"> WSGIPerInterpreterGIL On </WSGIInterpreterOptions> WSGIInterpreterOptions is the container directive that lets you scope settings to a particular sub-interpreter. The process-group= selector matches a daemon process group by name, or %{GLOBAL} for the embedded mode interpreter in Apache child processes. The application-group= selector further narrows to a specific application group inside that process, which is the same thing as a specific sub-interpreter. Both selectors are optional, and the most-specific match wins. On its own, the directive above does nothing useful. The sub-interpreter is configured to hold its own GIL but no requests are being routed into it yet. To actually use it, you can delegate a sub-URL of the existing application to that sub-interpreter using a <Location> block: <Location /suburl> WSGIApplicationGroup sub-interp-1 </Location> The end result is that requests to /suburl are dispatched into a second copy of the application running in sub-interp-1, which holds its own GIL, while everything else continues to run in the default application group with the process-wide GIL. Two halves of the same application can now execute Python bytecode in parallel inside one daemon process. There is a different shape that may suit a different setup. If your Apache configuration already has multiple WSGIScriptAlias directives pointing at distinct WSGI applications, and you have arranged for those applications to run in separate sub-interpreters of a single daemon process (as opposed to separate daemon process groups), then WSGIPerInterpreterGIL lets you opt the relevant sub-interpreters into their own GILs without rearranging the process layout. A note on cost. If the daemon process was previously hosting one sub-interpreter and you switch to hosting two, you now have two live copies of the application in that process, each with its own sys.modules, its own imported pure-Python modules, and its own per-interpreter C extension state. Memory use goes up. The trade is the same one you make when you add daemon processes, more memory in exchange for more parallel Python, but doing it within a single daemon process can still have advantages depending on how the application is provisioned and managed at the OS level. Whether one process with two sub-interpreters is preferable to two daemon processes with one sub-interpreter each is a judgement call about your specific deployment, not a universal answer. One more thing before moving on. There is a separate directive coming in this series called WSGIFreeThreading for use with free-threaded Python builds. The two are mutually exclusive on a single process, and the next post covers it on its own terms, so I will not muddy this one with the details. Which applications actually benefit The honest answer is fewer than the headline implies. Per-interpreter GIL helps for CPU-bound Python work that can be partitioned cleanly across requests, where you would otherwise be paying the cost of running additional daemon processes purely to dodge the GIL. Numerical work that is not already handled inside C code that releases the GIL, request-scoped computation, image processing, and similar. It is also worth being clear about what the directive does not do. Giving a sub-interpreter its own GIL only buys parallelism between sub-interpreters. Two concurrent CPU-bound requests that both land in sub-interp-1 still compete for that sub-interpreter's GIL and serialise against each other, exactly as they would have before. If all the heavy work funnels through one sub-interpreter, the directive has not bought you anything. The win comes from spreading the load across multiple sub-interpreters, each holding its own GIL. Which is why, for genuinely heavy CPU-bound throughput, scaling out with extra daemon processes is often still the cleaner answer; each daemon process gives you both an additional GIL and an additional set of OS-level resources to schedule against. For ordinary I/O-bound web applications, the win is much smaller. I/O already releases the GIL, threads in a single process can already overlap their waits for the database or the network, and adding daemon processes remains the simpler scaling lever. Per-interpreter GIL is a precision tool. It is most useful when you specifically want more parallel Python execution inside fewer processes, or when you already have multiple sub-interpreters in one process for isolation reasons and you would now like them to run in parallel as well. The gotchas A few things are worth being aware of before reaching for the directive. Sub-interpreters do not share Python state. Each sub-interpreter has its own sys.modules, its own imported copies of pure-Python modules, its own module globals. Any in-memory cache or singleton sitting in a module global is per-sub-interpreter. Anything you previously assumed worked process-wide now works only interpreter-wide. Each sub-interpreter pays its own import cost. Memory and startup time scale with the number of sub-interpreters. The point of per-interpreter GIL is parallelism within a single process; the cost is that every sub-interpreter independently imports the application and everything it depends on. The main interpreter remains special. To repeat the point from earlier, if your application is running in the main interpreter, which happens when WSGIApplicationGroup %{GLOBAL} is set, often because some C extension forced your hand, WSGIPerInterpreterGIL does nothing for it. The main interpreter always holds the process-wide GIL. Background threads must be non-daemon. Sub-interpreters that hold their own GIL do not allow Python code to create daemon threads. Anything your application spawns via threading.Thread must run as a non-daemon thread, which is the opposite of what most Python code defaults to when it wants a worker that quietly exits with the process. That restriction comes with an awkward shutdown problem. Python only runs atexit handlers after it has tried to join non-daemon threads during sub-interpreter teardown, so the common pattern of signalling background workers to stop from an atexit handler will deadlock. In a mod_wsgi context the right answer is to hook mod_wsgi's own shutdown callbacks instead, which fire early enough to let your threads drain and exit cleanly. That shutdown API is worth a post of its own. For the purposes of this one, the point is that if your WSGI application relies on daemon threads or atexit-driven cleanup, this is the one situation where enabling WSGIPerInterpreterGIL may force application-side code changes. What this means for C extension authors This is the part that turns most attempts to enable WSGIPerInterpreterGIL into a hunt through the dependency tree, and it is the part I want extension authors to take seriously. Restrictions on what works under sub-interpreters are not new. mod_wsgi users have been running into the rough edges of the simplified PyGILState_Ensure / PyGILState_Release API in sub-interpreters for years. The WSGIApplicationGroup %{GLOBAL} directive exists in part as a pragmatic answer for extensions that assume there is only one interpreter in the process. Per-interpreter GIL tightens those rules further, but it does not invent a new category of problem. What does change is that explicit opt-in is now required. The extension must use PEP 489 multi-phase module initialisation. Extensions still using single-phase init will not be loaded into a sub-interpreter that holds its own GIL. The extension must also declare Py_mod_multiple_interpreters with the value Py_MOD_PER_INTERPRETER_GIL_SUPPORTED in its PyModuleDef_Slot array, like this: static PyModuleDef_Slot module_slots[] = { {Py_mod_exec, module_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {0, NULL}, }; Without that declaration, the import fails when a sub-interpreter that holds its own GIL tries to load the module. The failure happens on first import, not at server startup, so it can take a request through a code path that has not been touched in a while to expose it. Module state needs to be per-interpreter. Anything stashed in a C-level static (counters, caches, registered callbacks, type objects pointing at process-wide globals) breaks isolation between sub-interpreters and produces bugs that will not show up until two interpreters race over the shared state. The right answer is to move the state into module state retrieved via PyModule_GetState. Code still using the simplified PyGILState API needs to be reviewed too, or replaced with the explicit PyThreadState-based APIs where the assumption of a single interpreter does not hold. For operators, the message is the unglamorous one. Before turning WSGIPerInterpreterGIL on in any kind of production setting, work through every C extension your application pulls in, directly and transitively. "Works on Python 3.12" is not the same as "works under per-interpreter GIL". The popular extensions are working through these requirements on their own timelines, and the situation will keep improving, but right now it is still on you to check. What's next If you maintain a mod_wsgi deployment and the per-interpreter GIL story is interesting to you, please try the 6.0.0 release candidate against a real workload and file issues against the GitHub project for anything that breaks or behaves oddly. The whole point of the RC period is to find out what does not work before the final release goes out. The next post in this series will cover WSGIFreeThreading, the second new concurrency directive in 6.0.0 and the one that targets PEP 703 free-threaded Python builds. The constraints there are different again, and worth their own treatment. For reference: mod_wsgi documentation mod_wsgi 6.0.0 release notes Per-interpreter GIL and free-threading user guide WSGIPerInterpreterGIL directive documentation PEP 684: A Per-Interpreter GIL PEP 734: Multiple Interpreters in the Stdlib PEP 489: Multi-phase extension module initialization

25.05.2026 07:38:42

Informační Technologie
dnes

The previous post in this series covered the new WSGIPerInterpreterGIL directive in mod_wsgi 6.0.0 and the PEP 684 per-interpreter GIL feature that landed in Python 3.12. This post is about its sibling, WSGIFreeThreading, which targets PEP 703 free-threaded Python builds. The two directives sit next to each other in the mod_wsgi configuration vocabulary and they both opt processes into a non-default concurrency model, but the underlying mechanisms are quite different. Per-interpreter GIL gives each sub-interpreter its own lock. Free-threading removes the lock entirely. That distinction shapes everything below. What free-threading actually is Free-threading removes the GIL from CPython entirely. There is no process-wide lock to acquire and no per-interpreter lock to acquire. All threads in the process can run Python bytecode in parallel, in the same interpreter, against the same Python objects. This is fundamentally different from per-interpreter GIL, which keeps a GIL but gives each sub-interpreter its own one. Free-threading has no GIL at all. The price for this is a special CPython build. The feature is enabled at compile time with --disable-gil, and on platforms that distribute it the resulting binary is typically named python3.13t. The "t" suffix exists precisely so the free-threaded build can coexist on a system alongside the normal CPython build. Free-threading shipped as an experimental opt-in in Python 3.13 and continues to mature in 3.14. One useful detail to know is that a free-threaded build can still run with a GIL. The build supports both modes. What you get at runtime depends on what the embedder asks for. Which is the bridge into mod_wsgi's posture. mod_wsgi's posture: opt-in even on a free-threaded build If you compile and install mod_wsgi against a free-threaded Python, the default is still GIL-enabled. Nothing about your existing application behaviour changes until you say otherwise. The free-threaded build supports the mode; mod_wsgi declines to use it without explicit instruction. This is worth being clear about because the assumption most people will reach for is the opposite. Installing mod_wsgi against python3.13t does not automatically give you free-threading. It gives you the ability to opt in. The reason for the default is the one you can guess at. The ecosystem of C extensions is nowhere near ready for everyone to be on free-threading by default. Forcing it on across the board would silently break existing deployments the moment they happened to import an extension that has not been audited for thread-safe execution. Defaulting to GIL-enabled keeps the worst case "nothing changes". You only get the new behaviour when you ask for it. The opt-in is WSGIFreeThreading On. The directive is per process. Unlike WSGIPerInterpreterGIL, it cannot be scoped to a specific sub-interpreter inside a process. Free-threading is a property of the whole process or none of it. The combinatorial story The upside of keeping the default opt-in is the flexibility it leaves you with. Compile mod_wsgi against a free-threaded Python build and you have access to three different concurrency models, and you can mix them across daemon process groups within the same Apache instance. The three options: Process-wide GIL (the classic model, still the default) Per-interpreter GIL, where each sub-interpreter in a process holds its own GIL (covered in the previous post) Free-threading, where the process has no GIL at all A single Apache instance can have one daemon process group running free-threaded for a CPU-bound numerical workload that has been audited end-to-end, another running with per-interpreter GIL for an application whose extensions support PEP 684 but not PEP 703, and embedded mode left on the classic process-wide GIL. Pick the right model per workload. There is also an experimentation angle worth calling out. Comparing the behaviour of the same application under each of the three modes on the same machine is suddenly much easier. You can run the same WSGI application in three daemon process groups, configure each one differently, route a slice of traffic at each, and compare directly. The constraint to be aware of: within a single process, free-threading and per-interpreter GIL are mutually exclusive. If both apply to the same process, free-threading wins and the per-interpreter GIL setting becomes a no-op. The mix-and-match is across processes, not inside one. How to enable The simplest form, opting all processes into free-threading at server scope: WSGIFreeThreading On Selective opt-in for a specific daemon process group, using the WSGIInterpreterOptions container directive introduced in the previous post: <WSGIInterpreterOptions process-group="cpu-bound"> WSGIFreeThreading On </WSGIInterpreterOptions> And for the embedded mode interpreter in Apache child processes: <WSGIInterpreterOptions process-group="%{GLOBAL}"> WSGIFreeThreading On </WSGIInterpreterOptions> mod_wsgi-express has a convenience flag, --free-threading, that flips this on for its generated configuration. One important contrast with WSGIPerInterpreterGIL to make explicit. The application-group= selector is not meaningful for free-threading. Per-interpreter GIL is a property of an individual sub-interpreter, so it makes sense to scope down to one. Free-threading is a property of the process. You cannot opt one sub-interpreter inside a process into free-threading while leaving another sub-interpreter in the same process with a GIL. The granularity is the process. If you write a <WSGIInterpreterOptions> container with an application-group= selector and try to put WSGIFreeThreading inside it, mod_wsgi will ignore the setting and log a warning. What this means for your Python code In theory, a correctly written WSGI application is already thread-safe. The WSGI specification has always allowed servers to call the application from multiple threads concurrently, and mod_wsgi has been able to use threaded daemon processes for years. So strictly speaking, if you have been doing it right, you are most of the way there. In practice, an enormous amount of WSGI code is implicitly relying on what the GIL gives you for free, in a way most developers do not even realise they are relying on. The GIL ensures that bytecode-level operations serialise against each other. Patterns like incrementing a counter with counter += 1, setting a key in a shared dict with cache[key] = value, appending to a shared list with items.append(thing), or "check then set" lookups against shared state happen to be safe-ish under the GIL because the GIL boundary makes them effectively atomic in the cases that matter most. Without a GIL they are not atomic. They need explicit locks or genuinely atomic primitives. The shapes of code that are most likely to be quietly unsafe under free-threading are not exotic. Module-level mutable state (registries, caches, in-memory counters) is the most common pattern. Lazy initialisation without locks (if _thing is None: _thing = build()) shows up everywhere. Shared mutable objects passed around between threads via globals, memoisation decorators that mutate shared dicts, application singletons set up at import time, the list goes on. These patterns are pervasive in real applications and they are exactly the kind of thing that "has always worked fine under a threaded server" because the GIL has been silently saving them. This is not a mod_wsgi-specific concern. It is the general PEP 703 question that every application owner has to answer for themselves, every library author has to answer for their library, and that the ecosystem as a whole is going to spend years working through. But mod_wsgi is going to be one of the most realistic places to actually run free-threaded Python against a real workload, so it is likely to be where a lot of these latent bugs first surface. The defensible position. If your application has been deliberately audited for true concurrent execution, with real locks where shared mutable state is touched and no implicit reliance on the GIL for serialisation, you are most of the way there. Most code, including most mature Python libraries, has not been audited that way. Free-threading is not a trap, but it is genuinely a different correctness contract than the one most Python code was written against. Treat the opt-in accordingly. What this means for C extensions The previous post covered the C extension story for per-interpreter GIL in some detail. The rules for free-threading are a separate set of rules, related but distinct, and I will focus on the contrasts rather than restate the bits that overlap. An extension opts into free-threading by declaring Py_mod_gil = Py_MOD_GIL_NOT_USED in its PyModuleDef_Slot array. That declaration is the extension author asserting "I have been audited for execution without a GIL". Without it, CPython treats the extension as untrusted for free-threading. The interesting difference from per-interpreter GIL is the load behaviour. Per-interpreter GIL fails the import outright if an extension has not declared support. Free-threading does not. The extension loads, but as soon as it loads CPython silently re-enables the GIL for the entire process and emits a runtime warning. That is worth understanding because the failure mode is "your free-threading quietly turned off" rather than "your import broke". You may not notice for a while that everything is back to running under a GIL. The other requirements largely match the per-interpreter GIL story. PEP 489 multi-phase module initialisation is the prerequisite. Module-level static state in C becomes a data-race risk in a way it was not under the GIL, and the right answer is to move it into module state retrieved via PyModule_GetState, with proper locking applied where shared state is unavoidable. Code still using the simplified PyGILState API needs to be reviewed for its assumptions, though for different reasons than under per-interpreter GIL. For operators, the auditing message is the same as last time. Before turning WSGIFreeThreading on in any kind of production setting, work through every C extension your application pulls in, directly and transitively, and check whether each one declares free-threading support. An extension that loads under free-threading without complaint is not necessarily fine. It may just be the one that triggered the silent fallback to GIL-enabled. Which applications actually benefit CPU-bound Python work that can be parallelised across threads in a single process is the clear win. Two threads inside one free-threaded process can both run Python bytecode at full speed against the same objects in the same address space. There is no within-sub-interpreter serialisation caveat to qualify it with, in contrast to per-interpreter GIL where two requests in the same sub-interpreter still compete for that sub-interpreter's GIL. Under free-threading, there is no GIL to compete for. There are costs to be honest about. Free-threaded CPython carries a measurable single-threaded overhead compared with a normal CPython build, because the runtime has to do per-thread bookkeeping for object reference counts and various other things that the GIL was previously making free. The single-thread performance gap has been closing release-over-release, but it is still real, and the trade is parallel throughput for single-thread speed. If your workload does not have parallel Python execution to gain in the first place, enabling free-threading can leave you slower overall. For ordinary I/O-bound WSGI applications, the practical gain remains smaller for the same reasons as in the previous post. I/O already releases the GIL on a normal CPython build, threads in a single process already overlap their waits on databases and network, and adding daemon processes remains the simpler scaling lever for most web workloads. Free-threading is most interesting where you specifically have CPU-bound Python that would benefit from running concurrently inside one process, and where you can afford both the audit work and the per-thread overhead. What's next If you run mod_wsgi and the free-threading story is interesting to you, please install the 6.0.0 release candidate against a free-threaded Python build, try it against a real workload, and file issues against the GitHub project for anything that breaks or behaves oddly. Free-threading is genuinely new territory for embedded Python hosts, and the feedback from real deployments is what will catch the rough edges before the final release. The next post in this concurrency series will cover WSGISwitchInterval. That one is not another GIL mode; it is a tuning lever for adjusting how frequently the GIL is yielded between threads, which can help reduce GIL contention in some workloads. It only applies where there is a GIL to switch, so it is a no-op under free-threading. For reference: mod_wsgi documentation mod_wsgi 6.0.0 release notes Per-interpreter GIL and free-threading user guide WSGIFreeThreading directive documentation PEP 703: Making the Global Interpreter Lock Optional in CPython PEP 489: Multi-phase extension module initialization Previous post: Per-interpreter GIL in mod_wsgi 6.0.0

25.05.2026 01:00:00

Informační Technologie
1 den

Something has shifted in how we use AI. We still talk about “chatbots” and “prompts” and “getting a good answer.” But underneath those familiar words, a different kind of system has been quietly taking shape. One that doesn’t just answer your question. One that does something about it.This Agents Unpacked series is about that shift. Not the hype version, not the science-fiction version, but the practical reality of what it means when an AI system can act, remember, and persist — when it can take a goal and work toward it, rather than waiting for you to type the next message.If you have used ChatGPT, Claude, or Gemini to help with your work, you already know the issue: the answer comes back, it’s good, and then... the real work begins. This series is about what happens when the AI can do some of that real work too.The Half-Done FeelingYou ask an AI chatbot to draft a project proposal. It gives you a solid one — well-structured, sensible, ready to polish. Then you close the chat window, and the proposal lives nowhere. The assistant doesn’t remember it. It doesn’t know where to file it, who needs to see it, or what happened the last time you wrote a similar proposal. If you come back tomorrow, you’re starting from scratch.Or you ask it to research a topic. It gives you a good summary. But it didn’t check your existing notes first, it didn’t save what it found, it didn’t organise the sources, and it didn’t flag the gaps. The answer is useful. The process is incomplete.This isn’t a criticism of chatbots. They do exactly what they were designed to do: you ask, they answer. The problem is that real work doesn’t stop at the answer. The proposal needs filing, the research needs organising, the plan needs tracking. The chatbot gave you a great starting point and then left you to do everything that comes after.That gap between a useful answer and a finished job is where agentic AI enters the picture.What Changes When AI Can ActA chatbot is like a consultant you can phone. You describe the problem, they give you advice, and then you hang up and do the work yourself. Good advice (hopefully), but the consultant doesn’t pick up the phone again tomorrow and ask how it went.An agent is different. It’s more like a capable colleague you’ve given a desk, a filing cabinet, and access to your systems. It has a workspace. It can remember what happened yesterday. It can read files, search the web, send messages, run calculations, ask you questions — not just talk about doing those things, but actually do them. And given a goal, it can work out the steps itself.The difference sounds small. In practice it changes what you can delegate, what you can automate, and what you still need to do yourself.The Loop UnderneathEvery agent runs on an agentic loop. It sounds technical, but the pattern is surprisingly familiar:Observe — What is the situation? What did the user ask? What information is already available?Think — What needs to happen next? Is one step enough, or should this be broken into parts?Act — Use a tool, look something up, write a file, send a message.Repeat — Look at what happened, decide whether the job is done, and continue if it isn’t.A chatbot usually observes your message, thinks once, and replies. That’s steps one through three, then stop. An agent goes further: after it acts, it looks at the result. Was that enough? Did the web search return useful information, or does it need to try again with different terms? Did the first draft cover everything, or are there gaps to fill? Is the job actually done, or is there more to do?You might be thinking: chatbots already learned to use tools. Isn’t the agentic loop just that, plus one more step? Four items instead of three. But the gap between “can use a tool” and “decides whether to keep going” is not small. It is the difference between a system that performs a task and a system that pursues a goal. The first is impressive. The second changes what you can trust it to do unsupervised.That continuation — the decision to check, adjust, and keep going — is what makes the loop matter. A single action might solve a simple request. But most real tasks aren’t simple — they need a sequence of steps, each one informed by the result of the last.The loop is the architecture that turns language into work. Without it, you have a very clever answering system. With it, you have something that can move through a task, make intermediate decisions, recover from partial failures, and stop only when the job is actually done.Stephen: I don’t get why the ‘Repeat’ step is needed? Wouldn’t the ‘Act’ provide the output I need?A single action might solve a simple request. But most real tasks aren’t simple — they need a sequence of steps, each one informed by the result of the last. The ‘Act’ step does produce an output. But the output is not the same as the outcome.After ‘Act’ runs, the agent looks at what happened: Was that enough? Did the web search return useful information, or does it need different terms? Did the first draft cover everything, or are there gaps to fill? Is the job actually done, or is there more to do?That check — that ‘Repeat’ step — is what closes the gap between a technically complete action and a genuinely finished job. Without it, you have a system that acts and stops. With it, you have a system that works until the job is actually done.Subscribe nowTools Are the HandsAn agent isn’t just “a better language model.” It has capabilities — things it can actually do in the world. Those are called tools.Some tools are built in: read files, write files, run commands, search the web, inspect images. Others are external: send emails, query databases, call APIs, trigger workflows. The specific tools vary by platform, but the principle is the same — tools are the bridge between thinking and doing.Think of it like this: an LLM on its own is like a brilliant mind with no hands. Tools give it hands. The loop is what decides when and how to use them.Keeping TrackAn agent can also hold information across steps and sessions. It remembers what it has already tried, what worked, what you prefer, what is still outstanding. This is not a personality trait. It is the system keeping relevant context available over time — the same way you rely on a notebook or a project board when you are working on something complex.Stephen: So when the agent remembers my preferences, that’s like what you’ve done to write this article. You learnt my learning style, read my writing (including my writing about technical writing), absorbed my preferences, so you can adapt how you explain things. Is that roughly right?That is exactly right. What an agent does with memory is not mysterious. It is practical. The system can store what you told it, what it observed, what it tried, and what the result was. When you come back, it can pick up where it left off. When it is working on a long task, it can hold the overall goal in view while handling the individual steps. That continuity is what turns a series of disconnected exchanges into something that feels like a sustained conversation.You do not have to repeat yourself. The agent remembers. That is the difference — not just remembering facts, but maintaining a thread.A Concrete ExampleLet’s make this less abstract.Imagine you ask for help planning a short research trip to a city you haven’t visited before. You need flights, accommodation, a sense of the neighbourhoods, and a rough itinerary that fits your schedule.A chatbot might give you an excellent summary of the city, suggest some hotels, and recommend a few neighbourhoods. That’s genuinely useful. But then you have to: check whether those hotels are actually available on your dates, compare prices, figure out which neighbourhood works best for your meetings, build the itinerary around your existing calendar, and keep track of it all so you can adjust later.An agent can take that same request and do something different.It might:Check your calendar for available dates before suggesting anythingSearch for flights and filter by your preferred departure timesCross-reference hotel locations against the addresses you need to visitBuild a day-by-day itinerary that accounts for travel time between meetingsSave the whole plan somewhere you can find it and update it laterFlag the gaps — “I found flights and hotels, but you haven’t told me whether you need a visa”Filter results by your stored preferences — early-morning flights, boutique hotelsUse your past travel patterns to anticipate the kind of trip that fits your styleThe agent doesn’t just tell you about the city. It assembles a usable, integrated plan. It uses tools to search, compare, read your calendar, write the plan, and flag what is missing. It loops through those actions until the trip is actually planned or until it hits something it cannot resolve without your input.That is the difference between an answer and an outcome.The Key TransitionThe shift to understanding agents is not about capabilities. It is about the move from isolated exchanges to sustained work.A chatbot gives you an answer. An agent helps you reach an outcome. One is a single exchange; the other is a process. One is clever; the other is useful in a different way — not smarter, but more continuous.The loop is what makes that continuity possible. Observe, think, act, check what happened, adjust, and continue until the work is done.Once you see that pattern, you start to notice it everywhere. A junior colleague troubleshooting a problem is running a loop: try something, see if it worked, try something else. A project manager steering a complex task is running a loop: check the status, identify what needs attention, act, and review.The same pattern appears everywhere in life. A cook adjusts a recipe by tasting as they go. A teacher tries an explanation, sees whether the student understood, and tries a different approach if they didn’t.Stephen: So, tell me if I got this right: The agent loop is mimicking how we, humans, work.We understand the problem, get the relevant context, perform an action, look at the result of our action and then decide whether that solves our problem. If it doesn’t, we explore why, come up with a new plan, implement the new actions, and repeat the process.It feels like the agent is going through the same process.That is exactly right. The agent loop isn’t some exotic new form of intelligence. It’s a pattern humans use all day every day, made explicit and embedded in a system that can act. The insight isn’t that the AI has become more intelligent. It’s that the AI has gained the ability to persist, to use tools, and to continue — the same things that turn a one-off answer into real, completed work.That is why this moment in AI feels different from previous ones. It is not that models suddenly became smarter. It is that they gained the ability to take action in a loop, over time, toward a goal.What This Series Will DoThis series is for people like me (Stephen, not Priya!), who already understand how LLMs work, who have used chatbots like ChatGPT or Claude, and who are now hearing about “agents” and wondering what that actually means. I felt I was lagging in the AI world so I started this learning process to make sure I’m not left behind!We will move beyond the half-done feeling and into the architecture of agentic systems. We will look at what agents actually are, how they are structured, what tools and skills give them their power, how multiple agents can coordinate, and how to think about trust, evaluation, and oversight.We will also look at the platforms and frameworks that exist today — what they offer, how they differ, and what tradeoffs you are choosing when you pick one. This is not a manual for any one platform. It is a guide to understanding the category itself, so you can make good choices about whether, where, and how to use agentic AI in your own work.The field moves fast. Some tools that looked promising six months ago may be superseded by the time you read this. That is fine. The principles matter more than the products. If you understand the loop, the anatomy, and the tradeoffs, you can look at whatever the current landscape happens to be and know what you are seeing.Here’s the draft Table of Contents of this series in Agents Unpacked. This is likely to change as Priya and I progress through this project:Stephen’s Preface to Agents UnpackedPart I — The Mental ShiftChapter 1 — From Answer to Outcome (this post)Chapter 2 — Anatomy of an AgentChapter 3 — Skills, Tools, and the Action LoopPart II — Agents in PracticeChapter 4 — Why One Agent Is Often Not EnoughChapter 5 — Where Agents Are Actually UsefulChapter 6 — Delegation DesignPart III — Building and Trusting Agentic WorkChapter 7 — Designing Your First Agentic WorkflowChapter 8 — When Things Go Wrong: Evaluation, Guardrails, and TrustChapter 9 — What to Build Next<< Previous Post: Stephen’s Preface to Agents Unpacked>> Next Post: Coming SoonTable of Contentsstephengruppetta.com

24.05.2026 19:02:33

Informační Technologie
1 den

Like many, I started using chatbots when GPT whatever-version-it-was came out and took the world by storm. It was really not very good at the time (compared to today’s top-end chatbots), but it was clearly the start of something.But things moved quickly, and I couldn’t quite catch up. I was busy with, you know, actual work, family, and life.Then I started hearing lots of new terms, lots of new acronyms. I didn’t know what they were. I still don’t know what most of them are.Then it was all about agents. I remember clearly thinking to myself: “Is this really any different from the ChatGPT-type chatbots?”And here’s where this new series comes in. I decided to dive into agents and created a few. One of them is a learning tutor agent that I personalised to suit me.I gave the agent all my tutorials and books. I gave the agent all the articles I wrote about my views on learning and technical writing.I asked the agent to figure out from all this how I like to learn, how I like to communicate. I teach the way I like to learn, so it’s fine to put my teaching style in the mix. Then, I had a good long chat with my learning tutor agent to make sure we’re on the same page.I gave a name to my agent (I named all my agents!) My personalised tutor is Priya.This series is the joint effort between Priya and me to help me understand agents. What are they? How do they work?Yes, it’s AI-generated content. But...It’s generated by an AI that’s extremely well-versed in my style of learning and communication.I had an active role in steering and editing the content. Here’s how...What you’ll read in the following articles was created using the following process:Priya researched the topic following my brief and created a course outline.She drafted the first chapter.I read through the file, leaving comments and questions along the way, directly within the text.I marked some comments as private.I marked some comments as public.Priya revised the chapter by incorporating my comments and questions.She deleted the private comments from the text after making changes to address my comments.She kept my public comments and questions in the text, clearly marked as “Stephen’s questions”, and she answered them directly in the text.I reviewed the chapter again and left more comments, and Priya revised the chapter again. We iterated through this until I was happy with the final text. And I was happy with the final text when I felt I understood everything in it and all my questions had been answered.Priya then moves on to draft the second chapter, and the whole process starts again.I will post these chapters as they emerge from this process. This is how I’m learning this topic. Hopefully, they may help some other people, too.Here’s the planned table of contents for this Agents Unpacked series. But note, this may change!Stephen’s Preface to Agents Unpacked (this post)Part I — The Mental ShiftChapter 1 — From Answer to OutcomeChapter 2 — Anatomy of an AgentChapter 3 — Skills, Tools, and the Action LoopPart II — Agents in PracticeChapter 4 — Why One Agent Is Often Not EnoughChapter 5 — Where Agents Are Actually UsefulChapter 6 — Delegation DesignPart III — Building and Trusting Agentic WorkChapter 7 — Designing Your First Agentic WorkflowChapter 8 — When Things Go Wrong: Evaluation, Guardrails, and TrustChapter 9 — What to Build NextSubscribe now

24.05.2026 18:15:54

Informační Technologie
1 den

Last week was PyCon US in Long Beach California. As always, it was a jam-packed intense time. I’ll try to report on my experience. The videos aren’t uploaded yet, but I’ll link to them later when they are.This recap is longer than I’ve done in the past. I don’t know why, it’s just how it came out. I want to convey a sense of what I get out of PyCon and what you can get out of PyCon.ThursdayOpening receptionI came with five of my colleagues from Netflix. I got to the Thursday night reception with Anika (first PyCon) and Josey (first PyCon with me). They said, “we’re going to count how many people Ned says hi to!” They were at 16 after five minutes and gave up. I don’t blame them. The reception is a very social time, and I have lots of friends I really enjoy seeing there.New friends and backpacksBesides seeing old friends, one of the great things about unstructured time like the opening reception is meeting new people. Tower Research Capital was giving away full-size Osprey backpacks at their booth. This was easily the most appreciated swag at PyCon. At the booth a clump of us were wondering what was required to get one. While there I met Maria, Camila, and Vin√≠cius. They are from Brazil, and were very friendly. They will re-appear in this story a few times.BTW: nothing was required to get a backpack, just ask and you get one. Everyone was very impressed.VolunteeringA good PyCon life-hack is to do some volunteer jobs. In particular, being a session runner is great. Pick a talk you want to go see anyway. Volunteer to be the session runner. Your duty is to go to the green room 15 minutes before the talk, meet the speaker, and help them get to the room on time and get set up. It’s a good way to make a connection with the speaker and help them at a particularly stressful time. It helps PyCon run smoothly. Also: the green room has coffee and snacks all day long!As it happens Vin√≠cius was doing a talk Friday about t-strings I wanted to see, so I signed up to be his session runner.Friday(No) breakfastFriday morning, I discovered that PyCon was not providing breakfast. This was unfortunate because conference meals are one of those unstructured times you can interact with lots of people. My strategy has usually been to look for a table that has people that don’t seem like me (in whatever ways), and meet people. Without a provided breakfast, I was instead eating a muffin in the quiet hotel lobby by myself. I understand why we were on our own for breakfast (conference food is expensive to provide), but I missed the congregating it encouraged.Maybe next year there will be a way to get people to gather over breakfast without paying conference-food prices.Fireworks disasterThe opening plenary by Deb Nicholson pumped the room up with excitement. But then came the opening “keynote” by Fireworks CEO Lin Qiao. I use the term sarcastically because it was not a keynote. It was an undisguised sales pitch for some kind of AI thing, complete with a QR code for discounts. It was a tone-deaf disaster of epic proportions. People (including me) walked out in the middle and were not shy about it.To make it even worse, Fireworks isn’t a sponsor of the PSF or of PyCon. Before the keynote, a few sponsors were given a chance to say a word. Anthropic gave $1.5M and spoke for two minutes about the importance of Python to their work. Then Fireworks had 45 minutes to sell products without giving anything!? It was extremely distasteful.The conference organizers were not at fault. Speaking to them afterwards, it was clear they were as blindsided as the rest of us. I don’t think anyone blamed PyCon for it, but it was definitely a missed opportunity. You want an opening keynote to lift spirits and launch people into the conference. Not a good start.Brazilian energyAt Vin√≠cius’ t-strings talk, his friends were in the front row waving Brazilian flags and occasionally blowing an air horn. They were also audible during large plenaries when Brazil was mentioned. I thought it was great and would love to hear more groups making noise when their segments or interests are in focus. It helps to give a sense of the breadth and scope of the community, and the strong sub-groups you might not have been aware of.Art open spaceMario Munoz ran an open space all Friday afternoon about Python and Art. I don’t consider myself an artist, but I’ve enjoyed making math-generated image projects. I got in touch beforehand to ask if my generative art projects would be on-topic. He said they would, so I dropped in.I showed some things I had made like truchet-tiled images or harmonic pendulums. The conversation quickly turned to, “is it art?” and if so, “who is the artist?” I created the programs, but then either a random number generator or the user clicking squiggles was making the choices. In the resulting image, who is the artist?I don’t have an answer, but it was interesting to hear people’s perspectives. I loved that in the midst of a highly organized conference with lots of “serious” topics like devops or security or AI, a few of us could sit quietly, noodle on a guitar and ponder what makes art.PyCon open spaces allow for all kinds of in-depth discussions and interactions. This was a perfect example.Mia’s docs changeAt last year’s PyCon, I met Mia, who was very interested to make some improvements to the Python docs. She landed one change, but then I didn’t hear from her over the rest of the year. We ran into each other again in the art open space, and we sat down afterwards to talk some more about contribution.We settled on a change to the docs home page, and she made that happen. Earlier this year I heard Jack Skinner on a podcast describe conferences as “co-working spaces with interruptions called talks.” Sitting with Mia was like a 30-minute sprint to find a change and get started on it enough so that the rest of the work could happen afterwards.Lightning talksSome of my favorite parts of PyCon are the lightning talk sessions. These are five-minute talks about anything, proposed and selected the day before. Because they are short, people will talk about all kinds of things. Because they are not “formal”, the selection process can select for variety rather than Importance.I keep coming back to the breadth of how Python is used and what it means to people. Lightning talks are a concrete way to see that.This year, some of the talks included: Adam Silkey’s rousing oration about running for local political office Choosing the ideal cat emoji Yapping Why you should run Python betas Cumbuca.dev, promoting diversity in tech in Brazil, run by my new friends Maria and Camila A PyPI that installs from floppy disks(?) Of course this is just a small sampling. I encourage you to find the lightning talks and watch them all.Lightning talk?At dinner Friday I mentioned an idea I’d had for a while for a lightning talk. I’d never given it because I was only excited about it during PyCon, and didn’t feel like I had the time to do the slides well enough. Stay tuned.SaturdayLightning talk!Saturday morning, I thought more about the lightning talk, and how making the slides was the blocker. So I tried using Claude to make the slides. I wrote an outline and tried a bit to get the slides built. When I saw that it seemed likely to work out, I submitted the talk for consideration. By lunch, I got the email saying I was on for Saturday night. Fun! I kept tweaking the slides over the course of the day.Pablo’s keynotePablo Galindo Salgado gave the morning keynote. He spoke in Spanish, with simultaneous captioning in English. He spoke with heart and passion about the collective effort to create Python. In particular he lamented the effects of the AI onslaught on the Python core team and on open source projects in general.Comparing open source work to building a cathedral, he took a long view on the skill- and community-building that are natural by-products of open source work. AI threatens to wash that all away, and maintainers aren’t sure what to do about it. We want to maintain the interpersonal dynamics that underpin everything we do, but AI makes it too easy to make all the wrong kinds of contributions and interactions.Pablo was emotional, personal, relevant, and inspirational. He connected with everyone in the room. On Friday I was joking that everyone agreed on two things: the backpack swag was great, and the Fireworks keynote was awful. Now everyone agreed on three things, because Pablo’s keynote was a keeper, one for the ages.PSF Members lunchThe PSF Members lunch is a place to have a lunch in a smallish room, with time for questions of the PSF. Two themes emerged from the questions: the first is that running a conference is very expensive and getting worse. 2027 will be in Long Beach again, but there’s no location chosen yet for 2028. I got the sense that the PSF is re-thinking the conference to maybe reshape the costs.The second theme was about non-US attendance. Many people chose not to travel to the US because of the current political situation, and I don’t blame them. When asked why we don’t do the main PyCon outside the US, Deb Nicholson pointed out that some US citizens would not be comfortable leaving the US and then trying to get back in. This is on top of the logistical problems of trying to run a conference outside your own country.JugglingSaturday afternoon, I continued a PyCon tradition: running a juggling open space. My strategy is to bring a couple dozen beanbags, camp out in a highly trafficked hallway, and teach anyone who’s interested. This year I had beanbags shipped to the hotel, and then gave most of those away at the end of the session. We had a lot of fun, some people learned some basics, and some were genuinely surprised to be gifted beanbags to take home.Long walkIt took longer than I thought to wrap up the juggling open space, so I had to hurry to the big stage for my lightning talk. But for some reason, we weren’t allowed to walk through the venue as we had that morning. We had to go outside and around a long block to walk back in a different entrance. That was bad enough, but I was given the wrong directions, so walked about twice that distance. I was very stressed and very thirsty, but did manage to get to the stage in time to get ready.Silence is GoldenMy lightning talk was “Silence is Golden”. It was about leaving quiet time during discussions so that reluctant speakers can find a place to insert themselves. What made the talk fun to do was riffing on PyCon’s usual Pac-Man rule, which says to leave a wedge open when standing in a circle so that new people can join you. The riff is to make a similar rule for time: if you draw a clock with a hand sweeping out the time that people are speaking, you can get a Pac-Man shape, with an open mouth for the time to be quiet so that someone new can speak.Making the clock animation was the thing I didn’t know how to do myself but Claude did for me. That let me focus on how to get the message across and not get lost in the mechanics of SVG details.I followed Simon Willison’s extremely energetic, fast-paced, loud lightning talk summarizing a year of LLM progress in five minutes (pelicans on bicycles), so it was an interesting contrast.Afterward people told me they really liked the talk, including Eric Holscher who had first formulated the Pac-Man rule. Nice. One of the Sunday morning lightning talks mentioned “Silence is Golden”! That’s one of the great things about lightning talks: they can be inspired, created, proposed, selected, and presented all during the weekend.SundaySunday was low-key for me compared to the first days. Maybe I was really low on sleep. No, I definitely was. I tend to sleep at most four hours a night at PyCon.We had more lightning talks. amanda casari did another good keynote tapping into concern about AI and how it would affect our work. Rachell Calhoun and Tim Schilling did a keynote about how they run Djangonauts, an upskilling program for new contributors. All of the big-audience events helped to reinforce the overarching themes that bind us together: working with each other, for each other.In the final closing session, I was really pleased to see my Boston co-organizer Fay Shaw be awarded a PyLadies Award! She’s very energetic and richly deserved it.ReflectionsWhat I didn’t doThere are always far too many things happening at once to do everything I’d like. I didn’t attend any of the Security track, the Packaging Summit, the Maintainers’ Summit, the organizers’ open space, the PyLadies auction, and so on and so on. I didn’t do anything outside the conference center other than dinners. Maybe next year I’ll walk over to take a look at the Queen Mary.People there and people notI can think of a number of people I didn’t see at PyCon that I expected to. I know there were many from outside the US who stayed away. I think back to PyCons of the last decade, and the visible people who seemed central to Python and PyCon then, but who now no longer are and no longer attend. That’s OK, the individuals change over time, but the community retains its essential nature. Some of the visible faces now are actually quite new to PyCon. Someone who attended for the first time this year might be one of the driving forces next year.We live and breathe, we grow and evolve. We remain the same.

24.05.2026 11:04:21

Informační Technologie
1 den

Continuing the tour through the wrapt 2.2.0 release, the last piece worth a closer look is the new async support in wrapt.synchronized. The decorator has been part of wrapt from the start, but until 2.2.0 it only really did the right thing for synchronous code. Applying it to an async def function used to give the appearance of working without actually serialising anything, and the context manager form had no async variant at all. Both are now fixed. A quick recap of synchronized wrapt.synchronized is the bundled decorator for ensuring that a callable is only executed by one caller at a time. The lock it acquires is created lazily and attached to the right object depending on what is being decorated: a per-function lock for plain functions, a per-instance lock for instance methods, a per-class lock for class methods or when the decorator is applied to a class body, and so on. None of that bookkeeping is the caller's responsibility. import wrapt class Counter: def __init__(self): self.value = 0 @wrapt.synchronized def increment(self): self.value += 1 There is also a context manager form, where you supply the object that should own the lock. The decorator form and the context manager form share the same auto-created lock when they name the same object, so they can be mixed freely: counter = Counter() with wrapt.synchronized(counter): counter.value += 1 The lock used in both cases is a threading.RLock. That choice matters and I will come back to it. Where it fell apart on async Applying the same decorator to an async def method in wrapt 2.1.x looked promising at first glance. The call returned a coroutine, awaiting it ran the body, and nothing raised. It was only when you tried it under contention that the problem became visible: import asyncio import wrapt class Counter: def __init__(self): self.value = 0 @wrapt.synchronized async def inc(self): cur = self.value await asyncio.sleep(0.01) self.value = cur + 1 async def main(): c = Counter() await asyncio.gather(*(c.inc() for _ in range(10))) print(c.value) asyncio.run(main()) Run under wrapt 2.1.2, this prints 1. Ten tasks all read cur = 0, all sleep, all write 1 back. The lock attached to the instance was a threading.RLock, and it was acquired and released around the construction of the coroutine, not around the awaited body. By the time anything interesting happened, the lock was gone. The context manager form did not help either. There was no async with support, so writing: async with wrapt.synchronized(counter): ... failed with an AttributeError complaining about a missing __aenter__. If you wanted serialised access to a shared resource from async code, you were on your own. What 2.2.0 changes In 2.2.0 the decorator inspects the wrapped function and picks a different locking primitive when it sees a coroutine function: import asyncio import wrapt class Counter: def __init__(self): self.value = 0 @wrapt.synchronized async def inc(self): cur = self.value await asyncio.sleep(0.01) self.value = cur + 1 async def main(): c = Counter() await asyncio.gather(*(c.inc() for _ in range(10))) print(c.value) asyncio.run(main()) This now prints 10. The wrapper still returns a coroutine, but the lock acquisition and release happen inside that coroutine using await, so the awaited body is actually serialised across tasks. The lock attached to the instance in this case is an asyncio.Lock, stored under a different attribute (_synchronized_async_lock) than the synchronous version (_synchronized_lock). A class that mixes synchronous and asynchronous synchronized methods on the same instance therefore gets two distinct locks, which is what you want, because mixing threading and asyncio primitives on the same lock would not work anyway. The context manager form has gained an async variant alongside the synchronous one. The same call now supports both spellings, picking the right behaviour based on whether you write with or async with: async with wrapt.synchronized(counter): counter.value += 1 For plain async functions, async classmethods, and any other shape that wrapt's decorator machinery already knew how to dispatch on, the same rule applies. If the wrapped callable is async def, you get an asyncio.Lock and an async wrapper. If it is not, you get a threading.RLock and a synchronous wrapper. The choice between them is automatic. The reentrancy difference There is one place where the synchronous and asynchronous paths deliberately do not match up: the synchronous lock is reentrant and the asynchronous lock is not. Calling a synchronized method from inside another synchronized method on the same instance is fine in the synchronous case, because threading.RLock allows the same thread to acquire the lock more than once. The async equivalent deadlocks: import asyncio import wrapt class A: @wrapt.synchronized async def outer(self): return await self.inner() @wrapt.synchronized async def inner(self): return "done" async def main(): a = A() try: result = await asyncio.wait_for(a.outer(), timeout=0.5) print(result) except asyncio.TimeoutError: print("deadlocked") asyncio.run(main()) This prints deadlocked. The same outer then inner chain on synchronous methods would print done and move on. The reason the async case behaves this way is that the standard library does not provide a reentrant async lock. There is no asyncio.RLock, only asyncio.Lock. Whether one ought to exist has been a recurring discussion on the Python issue tracker and on discuss.python.org for the better part of a decade, and the short version is that there is no agreement. The case for adding one is the obvious one. Code being ported from a synchronous codebase often relies on the reentrancy of threading.RLock to allow public methods that take a lock to call other public methods that take the same lock. Without a reentrant async equivalent, the same restructuring work has to be done by hand. The case against is partly about scope (every primitive in the standard library carries a maintenance cost) and partly about the conceptual mismatch between threads and tasks. threading.RLock is reentrant per thread, and a thread is a long-lived identity that a function can simply ask about. The analogous identity in async code is the current task, which is well defined but feels less stable to reason about: tasks are cheap, can be created mid-call, and suspend at every await. A reentrant lock keyed on the current task can paper over genuine design problems where one task ends up holding a lock across an await that gives another piece of code a chance to re-enter, in ways that are much easier to spot when the lock simply refuses to be acquired twice. There are third-party packages that implement reentrant async locks for people who want them, but wrapt deliberately stays in step with the standard library here. The synchronous side uses threading.RLock because that is what the standard library provides; the async side uses asyncio.Lock for the same reason. The practical consequence is that the usual workaround for non-reentrant locks applies on the async side. Public methods that acquire the lock should delegate to private helpers that assume the lock is already held: import asyncio import wrapt class Counter: def __init__(self): self.value = 0 @wrapt.synchronized async def add_two(self): await self._incr() await self._incr() return self.value async def _incr(self): cur = self.value await asyncio.sleep(0.001) self.value = cur + 1 async def main(): c = Counter() await asyncio.gather(*(c.add_two() for _ in range(5))) print(c.value) asyncio.run(main()) That prints 10, with the lock acquired exactly once per call to add_two. The pattern is a bit more disciplined than relying on reentrancy, but it makes the locking boundaries explicit, which is no bad thing in async code. Wrapping up The full set of changes to wrapt.synchronized is in the changelog, and the decorator itself is documented on the bundled decorators page. The feature is in wrapt from 2.2.0 onwards, with the usual recommendation to grab the latest release from PyPi since there have been follow-up releases on the 2.2.x branch. Issues and questions, as ever, go to the issue tracker on Github.

24.05.2026 10:00:00

Informační Technologie
1 den

Most decorators leave the function's outward shape alone. The same parameters go in, the same return type comes out, and inspect.signature and inspect.iscoroutinefunction give the same answers they would have given for the undecorated function. Sometimes you want a decorator that actively changes that shape. Adds or removes a parameter. Changes the return annotation. Turns a sync function into something that should be awaited, or runs an async function to completion so it can be called from sync code. The mechanics of doing the work in the wrapper body are usually straightforward. The harder part is making sure that downstream tools, which decide how to call or treat the function based on what introspection tells them, see the shape of the wrapper rather than the shape of the wrapped target. wrapt has had a partial answer to this for a long time via the adapter argument on @wrapt.decorator. The 2.2.0 release replaced that with a cleaner standalone with_signature decorator and added a new piece, mark_as_sync / mark_as_async, for the calling-convention side that the existing API did not address at all. There are also a couple of convenience bridges, async_to_sync and sync_to_async, that do the bridging and the marking together for the common cases. What introspection is for When this post talks about introspection, it means runtime introspection. Specifically, the answers given by inspect.signature, inspect.iscoroutinefunction, inspect.isasyncgenfunction, inspect.isgeneratorfunction and their friends, computed from the function object after the program has started running. This is distinct from static type checking. mypy and pyright work from source-level type hints before the program runs and rely on different mechanisms (typing.ParamSpec, typing.Concatenate, properly annotated wrapper signatures and so on). The wrapt decorators in this post fix up runtime introspection. They do not, in general, satisfy a static type checker. That is a separate problem with separate tools. The runtime side matters because a noticeable amount of modern Python ecosystem behaviour is driven by it. FastAPI inspects function signatures to build request parsing and parameter validation. ASGI frameworks ask iscoroutinefunction to decide whether to await a handler directly or dispatch it to a threadpool. pytest-asyncio decides whether to treat a test as async based on the same check. Click and Typer build their CLIs from inspect.signature of the command function. Sphinx and similar doc tooling pull signatures the same way. Each of these is making a real decision based on what introspection says, and if a decorator silently lies about its shape the decision goes wrong. The signature side: the old way wrapt shipped a way to handle this from very early on, via the adapter argument on @wrapt.decorator. The argument takes a prototype function whose signature is borrowed and presented as the decorated function's: import wrapt def _prototype(payload): pass @wrapt.decorator(adapter=_prototype) def inject_session(wrapped, instance, args, kwargs): return wrapped("session#1", *args, **kwargs) @inject_session def handle(session, payload): return f"{session} processing {payload}" import inspect print("call result :", handle("hello")) print("introspected sig :", inspect.signature(handle)) Output: call result : session#1 processing hello introspected sig : (payload) The user's handle function is defined with (session, payload). The decorator hides the session parameter and presents the result as (payload), while internally still calling the real handle with a session it provides. inspect.signature reports the shape the user actually sees, not the underlying. The adapter argument also accepts an inspect.getfullargspec() tuple or a formatted argspec string, and there is a wrapt.adapter_factory(...) helper for cases where the prototype has to be generated lazily. The catch is twofold. First, the prototype has to be specified on the decorator factory call, which separates it from the wrapper body and makes the whole thing a little harder to read. Second, the adapter argument is being deprecated in favour of the standalone wrapt.with_signature decorator described below. The signature side: with_signature The 2.2.0 replacement is wrapt.with_signature. It is a standalone decorator that overrides what inspect.signature reports for a callable, without changing what the callable actually accepts when called. It takes exactly one of three keyword arguments. The simplest form is prototype=, which borrows the signature from a dummy function: import inspect, wrapt def _prototype(payload: str) -> str: pass @wrapt.with_signature(prototype=_prototype) def handle(*args, **kwargs): return f"session#1 a:{args[0]}" print("call result :", handle("hello")) print("signature :", inspect.signature(handle)) Output: call result : session#1 a:hello signature : (payload: str) -> str The body of handle accepts *args, **kwargs because the implementation needs to be flexible (or in the decorator case, because that is what the wrapper signature is). Introspection sees the prototype's (payload: str) -> str instead. The second form is signature=, which takes a prebuilt inspect.Signature object. This is useful when the parameter list has to be assembled programmatically: sig = inspect.Signature( parameters=[ inspect.Parameter("payload", inspect.Parameter.POSITIONAL_OR_KEYWORD, annotation=str) ], return_annotation=str, ) @wrapt.with_signature(signature=sig) def handle(*args, **kwargs): return f"session#2 b:{args[0]}" The third form is factory=, which takes a callable that receives the wrapped function and returns either a Signature or a prototype. This is the right choice when the presented signature is derived from the wrapped function's own signature. A factory that strips the first parameter, for instance, would let an "inject the first argument" decorator present whatever the underlying function had with the first slot removed: def strip_first(wrapped): s = inspect.signature(wrapped) return s.replace(parameters=list(s.parameters.values())[1:]) @wrapt.with_signature(factory=strip_first) def handle(*args, **kwargs): return f"session#3 c:{args[0]}" When used together with @wrapt.decorator, the stacking matters. with_signature applies to whatever it directly decorates, so the right place for it is at the use site (above the decorator-built decorator applied to the user's function), or baked into a custom decorator factory that applies it to the wrapped result. Stacking it above a @wrapt.decorator-built decorator definition does not propagate the signature override to the final wrapped result. A clean pattern for an "inject this argument" decorator that uses with_signature looks like: def _prototype(payload): pass @wrapt.decorator def _wrap(wrapped, instance, args, kwargs): return wrapped("session", *args, **kwargs) def inject_session(fn): return wrapt.with_signature(prototype=_prototype)(_wrap(fn)) @inject_session def handle(session, payload): return f"{session} processing {payload}" inspect.signature(handle) reports (payload). The decorator is a regular function that composes wrapt.decorator and wrapt.with_signature explicitly. A bit more code than the adapter= form, but the pieces are more visible, and wrapt.with_signature is itself reusable in plenty of cases that have nothing to do with @wrapt.decorator. The important property that with_signature only touches argument-shape code-object flags. The calling-convention bits are left alone. That cleanly separates this concern from the next one. The calling-convention side: the problem Suppose a third-party decorator (or one you wrote a while back) takes an async def function and produces a sync callable that runs the coroutine to completion. The body of the decorated function is async, but the result is something you call without await. What does inspect.iscoroutinefunction say? import asyncio, inspect, wrapt @wrapt.decorator def run_to_completion(wrapped, instance, args, kwargs): return asyncio.run(wrapped(*args, **kwargs)) @run_to_completion async def fetch(): return 42 print("call result :", fetch()) print("iscoroutinefunction:", inspect.iscoroutinefunction(fetch)) Output: call result : 42 iscoroutinefunction: True Calling fetch() returns 42 because the decorator collapsed the async work to a sync call. But inspect.iscoroutinefunction(fetch) still returns True, because introspection sees the underlying async def. Anything that asks "is this a coroutine function?" to decide what to do with fetch will pick the wrong path. An ASGI framework would await it. pytest-asyncio would treat it as async. Each of those is now making a decision that does not match the actual calling convention. The mirror case is the same shape in reverse. A plain def function wrapped by something that returns a coroutine reads as not-a-coroutine through introspection, but actually requires await. with_signature does not help here. It is the wrong tool. The calling-convention bits live in different co_flags slots. mark_as_sync and mark_as_async The 2.2.0 answer is a pair of small pass-through decorators that adjust the calling-convention bits and nothing else. They do not bridge anything. They only correct what introspection reports about a stack whose effective convention has already been changed by something else. The async-to-sync case becomes: import asyncio, inspect, wrapt @wrapt.decorator def run_to_completion(wrapped, instance, args, kwargs): return asyncio.run(wrapped(*args, **kwargs)) @wrapt.mark_as_sync @run_to_completion async def fetch(): return 42 print("call result :", fetch()) print("iscoroutinefunction:", inspect.iscoroutinefunction(fetch)) Output: call result : 42 iscoroutinefunction: False And the symmetric sync-to-async case: import asyncio, inspect, wrapt @wrapt.decorator def schedule(wrapped, instance, args, kwargs): async def runner(): return wrapped(*args, **kwargs) return runner() @wrapt.mark_as_async @schedule def compute(x, y): return x * y print("iscoroutinefunction:", inspect.iscoroutinefunction(compute)) print("awaited result :", asyncio.run(compute(6, 7))) Output: iscoroutinefunction: True awaited result : 42 It is worth being explicit about what the markers do not do. Putting @wrapt.mark_as_sync directly on an async def does not magically make it sync-callable. It only changes what iscoroutinefunction reports. The bridging from one convention to the other has to be done by some other piece of code in the stack. The markers exist so that introspection can be made to match the reality that something else has already established. Generator nuance There are four kinds of callable when you consider the generator/coroutine axes together: plain function, sync generator, coroutine function, async generator. The markers handle all four via an optional generator= keyword that takes None (default, preserve), True (mark as the generator variant of the chosen convention), or False (mark as the non-generator variant). For example, if an inner decorator drains an async generator into a list and presents the result as a plain sync function returning that list, mark_as_sync(generator=False) makes introspection see "plain sync function" rather than the underlying "async generator function". The mirror case for async iterables produced from a sync generator uses mark_as_async(generator=True). Most code only needs the default form, but the option is there when both axes need to move at once. async_to_sync and sync_to_async For the common case of actually bridging between conventions, 2.2.0 bundles two convenience decorators. They do the bridging and apply the right marker, so introspection lines up without a separate mark_as_* step. wrapt.async_to_sync runs the coroutine to completion via asyncio.run on each call, and marks the result as sync: import inspect, wrapt @wrapt.async_to_sync async def add(a, b): return a + b print("iscoroutinefunction:", inspect.iscoroutinefunction(add)) print("call result :", add(2, 3)) Output: iscoroutinefunction: False call result : 5 wrapt.sync_to_async is the mirror. It schedules a sync function onto the default executor via loop.run_in_executor, and marks the result as async: import asyncio, inspect, wrapt @wrapt.sync_to_async def mul(a, b): return a * b print("iscoroutinefunction:", inspect.iscoroutinefunction(mul)) print("awaited result :", asyncio.run(mul(4, 5))) Output: iscoroutinefunction: True awaited result : 20 These are the same family of utility as asgiref.sync.sync_to_async and asgiref.sync.async_to_sync, which Django leans on heavily for mixing sync and async code. The wrapt versions are smaller and pre-marked, which is the convenient thing. If you need richer behaviour, like explicit executor selection or structured concurrency through anyio, the third-party tools are still the right call. In that case you can apply wrapt.mark_as_sync or wrapt.mark_as_async after the third-party bridge to bring introspection into line: @wrapt.mark_as_sync @third_party_async_to_sync async def work(...): ... Composing both axes The whole point of keeping with_signature and the markers as separate decorators is that they touch different parts of the function's code-object flags and can be combined freely. A decorator that changes both the parameter shape and the calling convention works by stacking them in the natural order: import inspect, wrapt def _prototype(payload: str) -> int: ... @wrapt.async_to_sync @wrapt.with_signature(prototype=_prototype) async def handler(*args, **kwargs): return len(args[0]) print("signature :", inspect.signature(handler)) print("iscoroutinefunction :", inspect.iscoroutinefunction(handler)) print("call result :", handler("hello")) Output: signature : (payload: str) -> int iscoroutinefunction : False call result : 5 with_signature overrides the signature presented by introspection. async_to_sync bridges the async body to a sync call and marks the result accordingly. The two concerns are completely independent and the stacking just falls out of which one needs to be closer to the function (with_signature) and which produces the outer wrapper (async_to_sync). Wrap up The summary of where to reach for each piece is short. For signature changes, use wrapt.with_signature for new code. The adapter= argument to wrapt.decorator still works and is not going away tomorrow, but it is being deprecated in favour of with_signature, which is the cleaner option going forward. For calling-convention changes, where introspection needs to report a different sync/async/generator answer than the underlying function would suggest, use wrapt.mark_as_sync or wrapt.mark_as_async to correct what introspection reports. Remember that the markers do not bridge anything. They annotate a stack whose effective convention has already been changed. For the common bridging cases, wrapt.async_to_sync and wrapt.sync_to_async do the bridging and the marking together. For more sophisticated async runtime needs, keep using asgiref or anyio and apply the markers afterwards. The full set of these tools is documented across signature changing decorators, signature override and calling convention markers and adapters. Release notes are in the changelog, the latest release is on PyPi, and issues go to the issue tracker on Github.

24.05.2026 08:00:00

Informační Technologie
1 den

This post is for the people who write APM agents, tracers, profilers, debuggers, and anything else that instruments Python code without asking the user to change it. Everyone else is welcome along. The reason I want to call out the audience up front is that wrapt was created for this kind of work, and the original purpose is sometimes obscured by how widely the project has been adopted for its decorator API. The decorator side of wrapt (which the recent posts on stateful decorators and per-instance lru_cache have covered) grew out of needing reliable building blocks for monkey patching, not the other way around. There is a side of wrapt that, until April 2026, had no dedicated page in the official documentation. I have covered it in various conference talks over the years, but that is not the same thing as having proper docs. The mechanism for deferred monkey patching, registering a patch against a module that has not been imported yet, with the patch only applied when the module is later imported, has been part of wrapt from day one. The monkey patching documentation page finally landed in the lead-up to the 2.2.0 release, which also added a small ergonomic piece. A new ? modifier on module names closes the last awkward gap in how the deferred form composes with the convenient decorator syntax. So this post is amplification of a pattern that has been there all along, not breaking news. The new modifier is just polish. With Python 3.15 about to ship PEP 810 explicit lazy import syntax, the timing matters. Any instrumentation library that force-imports its target modules at agent startup is now actively undoing user-level lazy imports. That has always been a little impolite for cold-start performance. With 3.15 it becomes a direct conflict with how users want to write their code. A monkey patching primer The smallest useful piece of wrapt's monkey patching API is wrap_function_wrapper. You give it a module, the dotted name of an attribute on that module, and a wrapper function. It replaces that attribute with a FunctionWrapper that calls your wrapper around the original. A timing wrapper on json.dumps looks like this: import json import time import wrapt def time_call(wrapped, instance, args, kwargs): start = time.perf_counter() try: return wrapped(*args, **kwargs) finally: elapsed = (time.perf_counter() - start) * 1e6 print(f"json.dumps took {elapsed:.0f} us") wrapt.wrap_function_wrapper("json", "dumps", time_call) print(json.dumps({"a": 1, "b": [2, 3]})) Output: json.dumps took 16 us {"a": 1, "b": [2, 3]} The wrapped, instance, args, kwargs signature of time_call is the same uniform wrapper signature that @wrapt.decorator uses, and that the stateful decorators post has already shown in the decorator context. That is not a coincidence. The decorator API in wrapt is built on top of this same wrapper mechanism, not the other way around, so the body you would write for a @wrapt.decorator-style decorator is the same body you would write for a monkey patch. Whatever you have learned about writing wrappers in the decorator context carries straight over. The user code that calls json.dumps does not change. The instrumentation is added entirely by wrap_function_wrapper. That is the whole point. APM agents and similar tools want to add visibility to third-party code without asking the user to modify it. The forced-import problem wrap_function_wrapper takes the module name as a string and imports the module to find the attribute to wrap. The act of registering the patch loads the target. import sys import wrapt def trace(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) print("before:", "xml.etree.ElementTree" in sys.modules) wrapt.wrap_function_wrapper("xml.etree.ElementTree", "fromstring", trace) print("after :", "xml.etree.ElementTree" in sys.modules) Running this prints: before: False after : True For a single module that is mildly wasteful. For an APM agent that supports, say, requests, httpx, urllib3, aiohttp, django, flask, fastapi, sqlalchemy, psycopg, redis, pymongo and kafka-python, importing the agent loads every one of those modules at agent startup, regardless of which the user's app actually uses. The price shows up in three places. Cold start time gets a noticeable chunk added, which matters disproportionately in serverless and short-lived worker environments where the process lifetime is measured in seconds. Memory holds code that is never going to be called. And the user's own lazy import statements get silently undone, because by the time their code runs the modules are already loaded. The long-standing answer The mechanism that solves all three problems has been in wrapt from the early days. The idea originally came from PEP 369, which proposed post-import hooks for the Python standard library. That PEP was withdrawn, but wrapt provides its own implementation via a sys.meta_path finder. The low-level entry point is register_post_import_hook(hook, name). The hook is a callback that takes the module as its argument and runs once the named module is imported. If the module is already imported when the hook is registered, the hook fires immediately. The decorator form, when_imported(name), is the one most code uses: import sys import wrapt def trace_reader(wrapped, instance, args, kwargs): print("[traced csv.reader]") return wrapped(*args, **kwargs) @wrapt.when_imported("csv") def install(module): wrapt.wrap_function_wrapper(module, "reader", trace_reader) print("after register:", "csv" in sys.modules) import csv print("after import :", "csv" in sys.modules) for row in csv.reader(["a,b,c"]): print("row:", row) Output: after register: False after import : True [traced csv.reader] row: ['a', 'b', 'c'] Two things to notice. Registering the hook does not touch sys.modules. The module is only loaded when the user's code does import csv. And the wrapping happens automatically as a side effect of that import, so the patched csv.reader is what the user code sees. This is the mechanism that every reputable APM agent already uses one way or another, because they had to. It just was not very visible from the outside. The decorator-form gap wrap_function_wrapper has a more convenient cousin called patch_function_wrapper which is the decorator form. It lets you keep the wrapper definition at module top level rather than nested inside a callback: @wrapt.patch_function_wrapper("html.parser", "HTMLParser.feed") def trace_feed(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) This is the form you really want for a patch registry. One decorated wrapper function per supported third-party target, all at the top level of one file. Easy to read, easy to grep, no nested closures. The catch, before wrapt 2.2.0, was that this decorator form force-imported its target the same way wrap_function_wrapper did: import sys import wrapt print("before:", "html.parser" in sys.modules) @wrapt.patch_function_wrapper("html.parser", "HTMLParser.feed") def trace_feed(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) print("after :", "html.parser" in sys.modules) before: False after : True The lazy alternative meant restructuring into a when_imported callback with the wrapper defined inside it. Workable but ugly, especially repeated across a dozen targets, and you lose the clean "one decorated function per target" layout that makes a patch registry readable. The ? modifier in 2.2.0 wrapt 2.2.0 closes the gap by recognising a trailing ? on a module name. With the ?, both wrap_function_wrapper and patch_function_wrapper defer registration via a post-import hook when the target module is not yet loaded. If the module is already in sys.modules, the patch is applied immediately. Same behaviour as before, just without the side effect of forcing the import. import sys import wrapt def trace(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) wrapt.wrap_function_wrapper("gzip?", "compress", trace) print("after register (with ?):", "gzip" in sys.modules) import gzip print("after import :", "gzip" in sys.modules) after register (with ?): False after import : True And the decorator form, which is the case that actually motivated the change: import sys import wrapt @wrapt.patch_function_wrapper("tempfile?", "mkdtemp") def trace_mkdtemp(wrapped, instance, args, kwargs): print("[traced tempfile.mkdtemp]") return wrapped(*args, **kwargs) print("after register (with ?):", "tempfile" in sys.modules) import tempfile print("after import :", "tempfile" in sys.modules) print("mkdtemp:", tempfile.mkdtemp()) after register (with ?): False after import : True [traced tempfile.mkdtemp] mkdtemp: /var/folders/.../tmpktve96ix Under the hood, the ? form is genuinely just shorthand. The implementation in wrapt's patches.py is roughly: if target.endswith("?"): target = target[:-1] if target in sys.modules: return wrap_object(sys.modules[target], name, FunctionWrapper, (wrapper,)) def callback(module): wrap_object(module, name, FunctionWrapper, (wrapper,)) register_post_import_hook(callback, target) return None No new mechanism, no new dispatch path. The work is still done by the same register_post_import_hook that has been in wrapt for years. The benefit is purely the authoring style. @patch_function_wrapper("...?", "...") at top level is now an option that previously was not. Composition with PEP 810 lazy imports Python 3.15 ships PEP 810 explicit lazy imports. The user can write: lazy import requests and the import is deferred until the name requests is first used. The discussion in Lazy imports using wrapt covers the PEP's motivation in more detail. This raises a question that was not quite so sharp before. If a user's code uses lazy import for a module, and an APM agent registers a non-lazy wrap_function_wrapper for that module, what happens? # apm_eager.py — simulated APM patches import wrapt def trace(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) wrapt.wrap_function_wrapper("gzip", "compress", trace) # user_code.py — user's app import sys import apm_eager # APM agent loaded at process startup lazy import gzip print("after lazy import:", "gzip" in sys.modules) gzip.compress(b"hello") print("after first use :", "gzip" in sys.modules) Output: after lazy import: True after first use : True The user wrote lazy import gzip, but gzip is already in sys.modules by the time their import statement runs. The APM agent loaded it on the user's behalf. Whatever benefit the user expected from lazy import has been quietly undone. Switching the APM agent to use the ? form fixes it: # apm_lazy.py import wrapt def trace(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) wrapt.wrap_function_wrapper("gzip?", "compress", trace) With the same user code as before, this now prints: after lazy import: False after first use : True gzip is only loaded at the moment the user's code first touches it, and at that moment the patch fires too. Lazy patching and lazy imports compose correctly. Putting it together: a patch registry For an APM agent or similar, the practical pattern looks like this. A single file declares all the patches as a flat list of top-level decorated functions: # my_apm_patches.py import wrapt @wrapt.patch_function_wrapper("xml.etree.ElementTree?", "fromstring") def trace_fromstring(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) @wrapt.patch_function_wrapper("csv?", "reader") def trace_reader(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) @wrapt.patch_function_wrapper("gzip?", "compress") def trace_compress(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) @wrapt.patch_function_wrapper("html.parser?", "HTMLParser.feed") def trace_feed(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) Importing this module registers all four patches but loads none of the target modules: import sys import my_apm_patches targets = ["xml.etree.ElementTree", "csv", "gzip", "html.parser"] for m in targets: print(f" {m:30s} {'loaded' if m in sys.modules else 'not loaded'}") Output: xml.etree.ElementTree not loaded csv not loaded gzip not loaded html.parser not loaded Whichever modules the user's code actually imports is the set that ends up getting patched. The rest stay out of memory entirely. The agent has paid no cold-start cost for the targets the user does not care about, and the user's own lazy imports continue to do what they say on the tin. As a bonus, the test story is also better. The instrumentation library's test suite no longer needs every supported third-party package installed just to import the library, only the ones it actually exercises. What changed and what didn't Strictly speaking, nothing in wrapt 2.2.0 enables any behaviour that was not possible before. The deferred patching mechanism is the same register_post_import_hook it always was. What changed is the authoring ergonomics. The ? modifier lets you write the lazy version of a patch as concisely as the eager version, including in the decorator form that suits patch-registry files best. And the monkey patching docs page that landed in April 2026 finally makes the mechanism easy to discover. If you maintain instrumentation code that still force-imports its targets, Python 3.15 is a good prompt to refactor. The change is mechanical. Add a ? to the module name in each wrap_function_wrapper and patch_function_wrapper call. The behaviour for already-loaded modules is unchanged, and for not-yet-loaded modules the patch now fires when (and only when) the user's code actually imports them. The full release notes for wrapt 2.2.0 are in the changelog. The latest release is on PyPi, and issues go to the issue tracker on Github.

24.05.2026 06:30:00

Informační Technologie
1 den

Following on from the previous post on stateful decorators, there is another small addition in wrapt 2.2.0 worth a closer look. A new wrapt.lru_cache helper has been added that fixes the long-standing issues with using functools.lru_cache on instance methods. The thing I want to emphasise up front is that wrapt.lru_cache is not a replacement for functools.lru_cache. The actual caching is still done by the standard library implementation, all of its keyword arguments are passed straight through, and the eviction behaviour is identical. What wrapt.lru_cache adds is a thin layer on top, built using wrapt's decorator machinery, that fixes how the underlying functools.lru_cache is applied when the decorated function turns out to be a method on a class. What lru_cache gives you functools.lru_cache is a small but very useful decorator. You wrap a function with it and the function's return values are remembered, keyed on the arguments, up to some maximum cache size. Repeat calls with the same arguments skip the function body and return the cached result. from functools import lru_cache @lru_cache(maxsize=128) def expensive(n): print("computing", n) return n * n expensive(2) expensive(2) expensive(3) Running this prints computing 2 and computing 3 once each. For pure functions of their arguments this is exactly what you want. Where it falls apart It is when you reach for the same decorator on an instance method that things start to go wrong. The standard library implementation has no concept of the wrapped function being a method, so it treats self as just another argument and includes it in the cache key. That single design choice causes three distinct problems. Problem 1: instances share a single cache budget from functools import lru_cache class Computer: @lru_cache(maxsize=2) def compute(self, x): return x * 2 a = Computer() b = Computer() a.compute(1) a.compute(2) b.compute(1) b.compute(2) print(a.compute.cache_info()) The cache is a single shared structure attached to Computer.compute. With maxsize=2, four distinct (self, x) pairs across the two instances are competing for two cache slots. cache_info() reports hits=0, misses=4, currsize=2. With one hundred instances and the default maxsize=128, each instance ends up with rather close to a single cache slot of its own. Problem 2: cached instances cannot be garbage collected Because self is part of the cache key, the cache holds a strong reference to it. The instance can never go out of scope while there is a cached entry for one of its method calls: import gc, weakref from functools import lru_cache class Big: @lru_cache def compute(self, x): return x b = Big() ref = weakref.ref(b) b.compute(1) del b gc.collect() print(ref()) ref() returns the original Big instance rather than None. It is still alive, kept around by the cache, with no easy way to find or release it short of calling Big.compute.cache_clear() and dropping every other instance's cached results along with it. Problem 3: self must be hashable Cache keys have to be hashable. The standard library implementation therefore requires that self is hashable too. Any class that defines __eq__ without also defining __hash__ is implicitly unhashable, and the decorator will fail at call time: from functools import lru_cache class Record: def __init__(self, name): self.name = name def __eq__(self, other): return isinstance(other, Record) and self.name == other.name @lru_cache def upper(self): return self.name.upper() Record("a").upper() That raises TypeError: unhashable type: 'Record'. None of the function's actual arguments are involved in the failure; it is purely about self. The wrapt version The wrapt.lru_cache helper sidesteps all three problems by recognising when the decorated callable is being invoked as a method, and arranging for a separate functools.lru_cache-wrapped helper to exist for each decorated method on each instance. The helper is stored directly on the instance under an attribute named after the wrapped method, so for a method called compute the cache lives at instance._lru_cache_compute. The cache key is built from the genuine arguments only, with self providing the lookup of which cache to use rather than being a participant in the key. The same three examples now look like: import wrapt class Computer: @wrapt.lru_cache(maxsize=2) def compute(self, x): return x * 2 a = Computer() b = Computer() a.compute(1) a.compute(2) b.compute(1) b.compute(2) print(a.compute.cache_info()) Each instance has its own cache for compute with the full maxsize=2 budget. The cache_info() call here returns the stats for the cache attached to a (hits=0, misses=2, currsize=2), not a shared total. Calling b.compute.cache_info() reports its own independent set of numbers. If Computer had several @wrapt.lru_cache methods then each would get its own per-instance cache, stored under a separate attribute (_lru_cache_compute, _lru_cache_other_method, and so on), with no contention between them. The garbage collection case works correctly because each instance owns its own cache attributes, and when the instance is collected the caches stored on it go with it: import gc, weakref import wrapt class Big: @wrapt.lru_cache def compute(self, x): return x b = Big() ref = weakref.ref(b) b.compute(1) del b gc.collect() print(ref()) ref() now returns None. And unhashable instances are fine, because self was never part of the cache key in the first place: import wrapt class Record: def __init__(self, name): self.name = name def __eq__(self, other): return isinstance(other, Record) and self.name == other.name @wrapt.lru_cache def upper(self): return self.name.upper() print(Record("a").upper()) That prints A, with no TypeError. For plain functions, class methods and static methods (where there is no per-instance state to keep separate) wrapt.lru_cache defers to a single shared functools.lru_cache, so the behaviour is indistinguishable from using functools.lru_cache directly: @wrapt.lru_cache(maxsize=32) def factorial(n): return n * factorial(n - 1) if n else 1 What is and is not new here To restate the point at the top of the post, none of this is a new caching algorithm. The eviction strategy, the cache statistics, the keyword arguments, the CacheInfo tuple, the cache_info() / cache_clear() / cache_parameters() methods are all functools.lru_cache, untouched. What wrapt.lru_cache adds is the descriptor-protocol-aware machinery to ensure that for instance methods, the right cache is created and consulted, with no global cache pollution, no reference leaks, and no hashability requirement on the instance. This is the kind of problem wrapt exists to handle. The recommended way to write a decorator with wrapt gives you a uniform wrapper signature that knows whether it has been called as a function, instance method, class method or static method, and the lru_cache helper is essentially a small, focused use of that machinery to delegate to the standard library decorator in a way that respects the calling convention. The lru_cache helper is documented over on the bundled decorators page, and the full release notes for the rest of wrapt 2.2.0 are in the changelog. The feature is available from 2.2.0 onwards, although as before it is worth grabbing the latest release from PyPi since there have been follow-up releases on the 2.2.x branch. Issues and questions go to the issue tracker on Github.

24.05.2026 04:30:00

Informační Technologie
1 den

A new version of wrapt was released earlier this week. Version 2.2.0 introduces a small helper that makes it noticeably easier to write decorators that need to keep state across calls. It is the kind of thing that does not look like much until you try to write the equivalent code without it, so it is worth a closer look. The full release notes are in the changelog. What I want to walk through here is the stateful decorator side of the release, because it touches on something that has always been a bit awkward in plain Python. Why a decorator might need state The idea of a stateful decorator is straightforward enough. You attach a wrapper to a function, and the wrapper remembers something across invocations. Counting how many times the function has been called is the canonical example. Other examples include accumulating timing statistics, caching results in a way you want to inspect, tracking which arguments have been seen, or maintaining a registry of what the wrapped function has done. The complication is not the bookkeeping itself, it is exposing the state back to the caller. If a decorator is purely passive and does its work without anyone ever needing to look at the internals, state can live in a closure and nobody is any the wiser. Once you decide that the user of the decorated function should be able to ask "how many times has this been called?", you need a way to reach into that state from the outside. The closure approach The simplest pattern in plain Python is to push state onto the wrapper function as an attribute: import functools def call_tracker(func): @functools.wraps(func) def wrapper(*args, **kwargs): try: return func(*args, **kwargs) finally: wrapper.call_count += 1 wrapper.call_count = 0 return wrapper @call_tracker def add(x, y): return x + y add(1, 2) add(3, 4) print(add.call_count) Running this prints 2. That works fine for a regular function, but the moment you apply the same decorator to an instance method things get more subtle. The wrapper itself is still a function, so the descriptor protocol kicks in and self is passed through correctly. The state however lives on the single wrapper object that was created at class definition time, so it is shared across every instance of the class. Whether that is what you want depends on the use case, but you have no real control over it from the way the decorator is written. The class approach If you want to keep both the state and the wrapper logic together, the next natural step is to write the decorator as a class: import functools class CallTracker: def __init__(self, func): functools.update_wrapper(self, func) self.func = func self.call_count = 0 def __call__(self, *args, **kwargs): try: return self.func(*args, **kwargs) finally: self.call_count += 1 @CallTracker def add(x, y): return x + y add(1, 2) print(add.call_count) This works for plain functions. The problem appears when the same decorator is applied to a method: class Calculator: @CallTracker def add(self, x, y): return x + y Calculator().add(1, 2) That raises TypeError: add() missing 1 required positional argument: 'y'. The reason is that Calculator.add is now a CallTracker instance rather than a function. When the attribute is looked up via an instance, the descriptor protocol does not kick in, because instances of user-defined classes are not descriptors by default. The Calculator instance is therefore never bound to self in the wrapped function, and the call sees x as 1 with no value for y. You can fix this by adding a __get__ method to CallTracker to make it behave as a descriptor, but then you also need to think about whether each access creates a fresh bound version, how classmethod and staticmethod interact with it, what happens when the descriptor is accessed on the class versus the instance, and so on. There is a real amount of code involved in getting all of this right, and it is exactly the code that wrapt exists to provide. Doing it with wrapt wrapt handles the descriptor machinery for you. The recommended way to write a decorator with wrapt is to use @wrapt.decorator, which gives you a uniform wrapper signature across functions, instance methods, class methods and static methods. You always get wrapped, instance, args and kwargs, with instance set appropriately depending on how the call was made. Before version 2.2.0, layering state on top of that meant a little bit of manual plumbing. You had to construct the state object yourself, write the wrapper to close over it, then explicitly attach the state to the wrapper after the fact so it could be reached from outside. Something like this: import wrapt class CallTracker: def __init__(self): self.call_count = 0 def __call__(self, func): tracker = self @wrapt.decorator def wrapper(wrapped, instance, args, kwargs): try: return wrapped(*args, **kwargs) finally: tracker.call_count += 1 wrapped_func = wrapper(func) wrapped_func.tracker = tracker return wrapped_func It is not exactly painful, but it is noisy. You have to remember to assign the state attribute, you have to alias self so the closure captures it rather than something else, and the actual interesting code (the try/finally) is buried under boilerplate. The new helper In wrapt 2.2.0 the same decorator can now be written like this: import wrapt class CallTracker: def __init__(self): self.call_count = 0 @wrapt.bind_state_to_wrapper(name="tracker") @wrapt.decorator def __call__(self, wrapped, instance, args, kwargs): try: return wrapped(*args, **kwargs) finally: self.call_count += 1 The __call__ method is defined directly with the standard wrapt decorator signature, with an extra self at the front so it can reach the state on the CallTracker instance. The @wrapt.bind_state_to_wrapper descriptor sits on top of @wrapt.decorator and takes care of two things. When __call__ is accessed via an instance of CallTracker, it returns a wrapper that knows about the right self. And when that wrapper is applied to a function, the CallTracker instance is automatically attached to the resulting wrapped function under the name supplied in the name argument. Using it looks like: @CallTracker() def add(x, y): return x + y add(1, 2) add(3, 4) print(add.tracker.call_count) The output is 2. Where the previous approaches forced a choice between keeping state with the decorator class and supporting methods correctly, wrapt lets you have both. Applied to an instance method, the same decorator just works: class Calculator: @CallTracker() def add(self, x, y): return x + y calc = Calculator() calc.add(1, 2) calc.add(3, 4) print(calc.add.tracker.call_count) This also prints 2. The wrapper handles descriptor binding correctly, self is passed through to the underlying method, and the state attribute remains reachable on the bound version of the wrapper because attribute lookup on a bound function wrapper now falls through to the parent function wrapper. That last bit is another small change in 2.2.0 that I won't dwell on here, but without it the cleaner syntax above would not be reachable through an instance. A little extra polish One refinement worth pointing out is what to do when you want the decorator to be usable both with and without arguments. That is, the @CallTracker versus @CallTracker(call_count=100) distinction. Construction can be wrapped up in a static method on the class: class CallTracker: def __init__(self, call_count=0): self.call_count = call_count @wrapt.bind_state_to_wrapper(name="tracker") @wrapt.decorator def __call__(self, wrapped, instance, args, kwargs): try: return wrapped(*args, **kwargs) finally: self.call_count += 1 @staticmethod def track(func=None, /, *, call_count=0): tracker = CallTracker(call_count=call_count) if func is None: return tracker return tracker(func) You can now write either @CallTracker.track or @CallTracker.track(call_count=100) and get sensible behaviour in both cases. None of that is specific to wrapt, it is just the usual Python trick for optional-argument decorators, but it composes nicely with the rest. Why this matters The reason wrapt exists in the first place is that writing decorators that behave correctly across functions, instance methods, class methods and static methods is harder than it looks. The descriptor protocol, functools.wraps, the inspect module, and the time-honoured Python habit of "just stick it on the function as an attribute" all interact in slightly awkward ways once you try to combine them. The uniform wrapper signature in wrapt removes most of that friction. What bind_state_to_wrapper adds is the last missing piece for the common case of a stateful decorator. The state lives on the decorator class, the wrapper has direct access to it via self, and the state is exposed back to callers through a named attribute on the wrapped object with no extra plumbing. Documentation for both pieces is over in the decorators guide and the examples page if you want to look at the full set of variations. The feature is available in wrapt from version 2.2.0 onwards, although you should grab whatever the latest release is from PyPi since there have been follow-up releases on the 2.2.x branch since. If you are coming to this from the Wrapt version 2.0.0 announcement last year, it builds on the same BaseObjectProxy reshuffle that release prepared the ground for. As always, if you find any issues there is an issue tracker on Github.

24.05.2026 01:55:00

Informační Technologie
1 den

Pi is now part of Earendil, but in the important sense it is still Mario’s project. He has been living with its issue tracker longer than I have, and he has been exposed to the weirdness of the new form of agent traffic in Open Source projects for longer too. This post is mostly a reflection of my own experience after spending more time in the tracker, using Pi to work on Pi, and watching what I have learned about it so far. Slop Issues Unsurprisingly, we are using Pi to build Pi. That sounds like a cute dogfooding thing but it really helps understand what we do. An interesting effect of building with agents is that it changes the role of the issue tracker a tiny bit. The issue descriptions are not just messages from a user to a maintainer because we also use them as inputs for prompts in Pi sessions. It is something I might hand to my clanker1 and say: “understand this, reproduce it, inspect the code, and propose a fix.” That means the shape of the issue matters in a new way. A bad issue was always annoying, but at least a lot of issues were vague. Now we are also dealing with a class of issues that are 5% human and 95% clanker-generated and largely inaccurate shit. A bad issue that contains a plausible but wrong diagnosis creates extra work. The most frustrating failure mode right now is that people submit issues that are not in their own voice. They contain an observed problem somewhere, but it has been thrown into a clanker and the clanker reworded it and made a huge mess of it. Typically, it was prompted so badly that the conclusions produced are more often than not inaccurate but always full of confidence. The result is complete guesswork on root causes, fake-minimal repros, suggested implementation strategies, analogies to adjacent but often the wrong code, and long lists of error classes that might or might not matter. That is worse than no diagnosis. I don’t want to point to specific issues because I really do not want to bad mouth anyone, but it is frustrating. It is also frustrating because when I give that issue to Pi, Pi sees the wrong diagnosis too. It does not treat the issue body as a rumor. It treats it as evidence. It will happily go down the path that the issue already prepared for it, because the prose is confident and the code references look plausible. We use a custom slash command called /is, which specifically has this instruction in it: Do not trust analysis written in the issue. Independently verify behavior and derive your own analysis from the code and execution path. Unfortunately, it does not fully work, because when humans first throw their issue through the clanker wringer, their clanker expands scope almost immediately. What was once a very narrow and fact based bug observation, turns into a much expanded surface area full of hypotheses. So at least personally, I increasingly want issue reports to be condensed to what the human actually observed: I ran this command. I expected this to happen. This happened instead. Here is the exact error or log. That is enough. If you used an LLM to understand the problem, great, maybe leave it as a follow-up comment. But the issue and the issue text should be something you own. If you do not know the root cause, say that. I too can operate a clanker, and I would rather do this myself than use your slop. If your repro is a guess, say that. If the only hard fact is one stack trace, give me the stack trace and stop there. Slop Begets Slop That we’re seeing issues full of slop is just a result of the present day quality of these machines. Sadly, their failures in creating good issues extend to a lot of code that is generated. Not all of it, but a lot of code. Over and over I keep running into them over-engineering the hell out of issues and implementations. If you tell them that “this malformed session log crashes the reader,” the clanker will often add a tolerant reader. Then it will add a fallback, then maybe a migration, then more debug output, then a test for all of this. None of this is necessarily wrong in isolation, but it can be the wrong move for the system. At Pi’s core is a rather well-designed session log with invariants that must be upheld. The clanker’s present-day behavior is to just assume that no such invariants exist, and instead to make the system work with all kinds of malformedness, blowing up the complexity in the process. Almost always, the correct fix is not to handle the bad state, but to make the bad state impossible. This matters a lot for persisted data such as Pi session logs. They are opened, branched, compacted, exported, shared, and analyzed. The goal here is to never write bad session data. Yet if you just let the clanker roam freely, it will attempt to handle every case of bad data in the session log with a more permissive reader. I have complained about this plenty, but working on Pi’s code base continues to reinforce the point. This is one of the ways LLM authored code grows so much needless complexity. All these models see a local failure and try to locally defend against it. As maintainers we have to keep pulling the conversation back to the global invariant, which is harder than it should be, and it’s laborious. Volume Is The Problem Then there is the issue of volume. The tracker is receiving a lot of issues and PRs, and a significant fraction of them are clearly LLM-assisted. Some are good, none are excellent, and most are just bad. The total throughput is a maintenance problem by itself. As you might know, Pi’s issue tracker is automated to close all issues and pull requests from new contributors, and there is a manual process by which we might reopen some of them or approve individuals. So auto-close -> reopen -> close again is an interesting statistic for us to look at. I pulled the public GitHub tracker data while writing this over the last 90 days. Excluding Earendil members, that leaves 3,145 external issues and pull requests. Of those, 2,504 were auto-closed because they were from non-approved individuals. 17% were reopened. For pull requests the number is worse: less than 10% were merged. Many of the issues and PRs are complete slop and in some cases the humans did not even realize that they created them. Sources of low-quality spam include OpenClaw instances, as well as some skills that people put into their context that seemingly encourage issue creation. GitHub clearly is not built to deal with this new form of Open Source, but I’m increasingly feeling the need to put the blame less on GitHub than on all the people involved who make that experience painful. If your clanker shits on someone else’s issue tracker then it’s not the fault of GitHub, it’s yours alone. Careful Parallelism Pi might be built with Pi, but we’re quite far off today from where Bun and OpenClaw already are: fully detached, automated software engineering. Maybe we will reach that point, I don’t know. Today it does not seem like we know how to pull off a dark factory and we also don’t yet have the desire. That said, there is quite a bit of parallelism going on, and it is mostly for reproducing issues. The small setup we use for this is three tiny pieces in Pi’s own committed .pi folder. /is (for analyze issue) is a prompt for analyzing GitHub issues: it labels and assigns the issue, reads the full thread and links, then explicitly tells the agent not to trust the analysis in the issue and to derive its own diagnosis from the code. Then an extension adds a prompt-url-widget which watches the prompt before the agent starts, recognizes the GitHub issue or PR URL that /is (or the PR equivalent) put into the prompt, fetches the title and author with gh, renders that in a little UI widget, and renames the session. It also rebuilds that state on session start or session switch, so if we reopen an older investigation the window still tells the developer which issue it belongs to. In practice this means it’s possible to have several Pi windows open, each running /is against a different issue, and the UI keeps the investigations visually distinct while the agents do their independent reproduction and code reading. Once the investigations are done, one can work through them sequentially. To finish off everything, /wr (wrap it up) is the matching wrap-up prompt: it infers the GitHub context from the session, updates the changelog, drafts or posts the final issue comment with a disclaimer, commits only the files changed in that session, adds the appropriate closes #... when there is exactly one issue, and pushes from main. Open Source Is About Hard Problems Worth Fixing You will have noticed this already but Open Source in a post-AI world is under a strange new pressure. We are getting more code, more projects, and more issues. Projects appear with no real users, or a temporary audience of one, and even projects with thousands of stars can have a shelf life of weeks. For us, Pi’s harness layer is worth maintaining carefully because it solves hard coordination problems and creates a platform we and others can build on. We also know that coordination and cooperation lifts us all up. Many times the right answer is not to work around a problem locally, but to make the upstream behavior correct. Mario has been very good at refusing to make Pi paper over every misconfigured gateway, and we’re trying to preserve that discipline. When a gateway behaves correctly, everybody benefits. Sadly that type of thinking is quickly disappearing because these machines make local workarounds cheap, so code accumulates local defenses against every misbehavior. Instead of humans talking to humans about where a fix belongs, one human and one machine work around the problem in isolation. Keep in mind that AI has not increased the number of people who need software, or the number of maintainers who can review it. It has mostly increased the amount of code and the number of projects competing for attention. Some of that is healthy, but a lot of it fragments effort that should be shared. We need stronger foundations, not weaker ones. Open Source needs more collaboration, not more isolated work with a machine. Human communication is hard, and it is tempting to avoid it when you can sit alone with your clanker. But isolation is not where Open Source derives its value. The value is in the community and the structure that lets projects outlive their original creators. To me, clanker is a much preferable term for agent. Agency lies with humans, not with machines. Calling these things agents I still believe is a mistake, but alas.↩

24.05.2026 00:00:00

Informační Technologie
2 dny

This is to inform you about the new stable release of Nuitka. It is the extremely compatible Python compiler, “download now”. This release adds many new features and corrections with a focus on async code compatibility, missing generics features, and Python 3.14 compatibility and Python compilation scalability yet again. Bug Fixes Python 3.14: Fix, decorators were breaking when disabling deferred annotations. (Fixed in 4.0.1 already.) Fix, nested loops could have wrong traces lead to mis-optimization. (Fixed in 4.0.1 already.) Plugins: Fix, run-time check of package configuration was incorrect. (Fixed in 4.0.1 already.) Compatibility: Fix, __builtins__ lacked necessary compatibility in compiled functions. (Fixed in 4.0.1 already.) Distutils: Fix, incorrect UTF-8 decoding was used for TOML input file parsing. (Fixed in 4.0.1 already.) Fix, multiple hard value assignments could cause compile time crashes. (Fixed in 4.0.1 already.) Fix, string concatenation was not properly annotating exception exits. (Fixed in 4.0.2 already.) Windows: Fix, --verbose-output and --show-modules-output did not work with forward slashes. (Fixed in 4.0.2 already.) Python 3.14: Fix, there were various compatibility issues including dictionary watchers and inline values. (Fixed in 4.0.2 already.) Python 3.14: Fix, stack pointer initialization to localsplus was incorrect to avoid garbage collection issues. (Fixed in 4.0.2 already.) Python 3.12+: Fix, generic type variable scoping in classes was incorrect. (Fixed in 4.0.2 already.) Python 3.12+: Fix, there were various issues with function generics. (Fixed in 4.0.2 already.) Python 3.8+: Fix, names in named expressions were not mangled. (Fixed in 4.0.2 already.) Plugins: Fix, module checksums were not robust against quoting style of module-name entry in YAML configurations. (Fixed in 4.0.2 already.) Plugins: Fix, doing imports in queried expressions caused corruption. (Fixed in 4.0.2 already.) UI: Fix, support for uv_build in the --project option was broken. (Fixed in 4.0.2 already.) Compatibility: Fix, names assigned in assignment expressions were not mangled. (Fixed in 4.0.2 already.) Python 3.12+: Fix, there were still various issues with function generics. (Fixed in 4.0.3 already.) Clang: Fix, debug mode was disabled for clang generally, but only ClangCL and macOS Clang didn’t want it. (Fixed in 4.0.3 already.) Zig: Fix, --windows-console-mode=attach|disable was not working when using Zig. (Fixed in 4.0.3 already.) macOS: Fix, yet another way self dependencies can look like, needed to have support added. (Fixed in 4.0.3 already.) Python 3.12+: Fix, generic types in classes had bugs with multiple type variables. (Fixed in 4.0.3 already.) Scons: Fix, repeated builds were not producing binary identical results. (Fixed in 4.0.3 already.) Scons: Fix, compiling with newer Python versions did not fall back to Zig when the developer prompt MSVC was unusable, and error reporting could crash. (Fixed in 4.0.4 already.) Zig: Fix, the workaround for Windows console mode attach or disable was incorrectly applied on non-Windows platforms. (Fixed in 4.0.4 already.) Standalone: Fix, linking with Python Build Standalone failed because libHacl_Hash_SHA2 was not filtered out unconditionally. (Fixed in 4.0.4 already.) Python 3.6+: Fix, exceptions like CancelledError thrown into an async generator awaiting an inner awaitable could be swallowed, causing crashes. (Fixed in 4.0.4 already.) Fix, not all ordered set modules accepted generators for update. (Fixed in 4.0.5 already.) Plugins: Disabled warning about rebuilding the pytokens extension module. (Fixed in 4.0.5 already.) Standalone: Filtered libHacl_Hash_SHA2 from link libs unconditionally. (Fixed in 4.0.5 already.) Debugging: Disabled unusable unicode consistency checks for Python versions 3.4 to 3.6. (Fixed in 4.0.5 already.) Python3.12+ Avoided cloning call nodes on class level which caused issues with generic functions in combination with decorators. (Added in 4.0.5 already.) Python 3.12+: Added support for generic type variables in async def functions. (Added in 4.0.5 already.) UI: Fix, flushing outputs for prompts was not working in all cases when progress bars were enabled. (Fixed in 4.0.6 already.) UI: Fix, unused variable warnings were missing at C compile time when using zig as a C compiler. (Fixed in 4.0.6 already.) Scons: Fix, forced stdout and stderr paths as a feature was broken. (Fixed in 4.0.6 already.) Fix, replacing a branch did not accurately track shared active variables causing optimization crashes. (Fixed in 4.0.7 already.) macOS: Fix, failed to remove extended attributes because files need to be made writable first. (Fixed in 4.0.7 already.) Fix, dict pop and setdefault using with := rewrites lacked exception-exit annotations for un-hashable keys. (Fixed in 4.0.8 already.) Python 3.13: Fix, the __parameters__ attribute of generic classes was not working. (Fixed in 4.0.8 already.) Python 3.11+: Fix, starred arguments were not working as type variables. (Fixed in 4.0.8 already.) Python2: Fix, FileNotFoundError compatibility fallback handling was not working properly. (Fixed in 4.0.8 already.) Compatibility: Fix, loop ownership check in value traces was missing, causing issues with nested loops. Windows: Improved --windows-console-mode=attach to properly handle console handles, enabling cases like os.system to work nicely. Python2: Fix, there was a compatibility issue where providing default values to the mkdtemp function was failing. Windows: Fix, there were spurious issues with C23 embedding in 32-bit MinGW64 by switching to coff_obj resource mode for it as well. Plugins: Fix, the post-import-code execution could fail because the triggering sub-package was not yet available in sys.modules. UI: Fix, listing package DLLs with --list-package-dlls was broken due to recent plugin lifecycle changes. UI: Fix, --list-package-exe was not working properly on non-Windows platforms failing to detect executable files correctly. UI: Handled paths starting with {PROGRAM_DIR} the same as a relative path when parsing the --onefile-tempdir-spec option. Plugins: Followed multiprocessing forkserver changes for newer Python versions. Python 3.12+: Fix, generic class type parameters handling was incorrect. Python 3.12: Fix, deferred evaluation of type aliases was failing. Python 3.12+: Aligned sum built-in float summation with CPython’s compensated sum for better accuracy. Python 3.10+: Fix, uncompiled coroutine throw() return handling was incorrect, restoring completed coroutine results via StopIteration.value rather than exposing them as ordinary return values to the outer await chain. Python 3.13+: Fix, uncompiled coroutine cancel()/await suspension handling was incorrect, improved to ensure integration compatibility. macOS: Made finding create-dmg more robustly by also checking the Homebrew path for Intel and from PATH properly. Compatibility: Fix, class frames were not exposing frame locals. UI: Detected static-libpython problems, which affected some forms of Anaconda. Distutils: Rejected --project mixed with --main arguments as it is not useful. macOS: Fix, zig from PATH or from ziglang was not being used. Distutils: Fix, the wrong module-root config value was being checked for uv build backend. macOS: Fix, was attempting to change removed (rejected) DLLs, which of course failed and errored out. Python 3.14: Fix, tuple reuse was not fully compatible, potentially causing crashes due to outdated hash caches. Fix, fake modules were still being attempted to located when imported by other code, which could conflict with existing modules. Python 3.5+: Fix, failed to send uncompiled coroutines the sent in value in yield from. Fix, older gcc compilers lacking newer intrinsic methods had compilation issues that needed to be addressed. Standalone: Fix, multiphase module extension modules with post-load code were not working properly. Fix, Avoid using the non-inline copy of pkg_resources with the inline copy of Jinja2. These could mismatch and cause errors. Fix, loops could make releasing of previous values very unclear, causing optimization errors. Fix, incbin resource mode was not working with old gcc C++ fallback. Python 3.4 to 3.6: Fix, bytecode demotion was not working properly for these versions, also bytecode only files not working. Plugins: Added a check for the broken patchelf versions 0.10 and 0.11 to prevent breaking Qt plugins. Android: Allowed patchelf version 0.18 on Android. Windows: Fix, the header path for self uninstalled Python was not detected correctly. Release: Fix, inclusion of the pkg_resources inline copy for Python 2 to source distributions was missing. UI: Detected the OBS versions of SUSE Linux better. Suse: Allowed using patchelf 0.18.0 there too. Python 3.11: Fix, package and module dicts were not aligned close enough to avoid a CPython bug. Fix, unbound compiled methods could crash when called without an object passed. Standalone: Fix, multiphase module extension modules with postload. (Fixed in 4.0.8 already.) Onefile: Fix, while waiting for the child, it may already be terminated. macOS: Removed existing absolute rpaths for Homebrew and MacPorts. Python 3.14: Avoided warning in CPython headers. Python 3.14: Followed allocator changes more closely. Compatibility: Avoided using pkg_resources for Jinja2 template location for loading. No-GIL: Applied some bug fixes to get basic things to work. Package Support Standalone: Add support for newer paddle version. (Added in 4.0.1 already.) Standalone: Add workaround for refcount checks of pandas. (Fixed in 4.0.1 already.) Standalone: Add support for newer h5py version. (Added in 4.0.2 already.) Standalone: Add support for newer scipy package. (Added in 4.0.2 already.) Plugins: Revert accidental os.getenv over os.environ.get changes in anti-bloat configurations that stopped them from working. Affected packages are networkx, persistent, and tensorflow. (Fixed in 4.0.5 already.) Standalone: Added missing DLLs for openvino. (Added in 4.0.7 already.) Enhanced the package configuration YAML schema by adding the relative_to parameter for from_filenames DLL specification, avoiding error-prone purely relative paths. Standalone: Fix, flet_desktop app assets were missing, now preserving the packaged runtime and sidecar DLLs. Standalone: Added support for the tyro package. Standalone: Added data files for the perfetto package. Standalone: Added support for anyio process forking. Standalone: Added support for the plotly.graph package. Anaconda: Fix, dependencies for the numpy conda package on Windows were incorrect. Plugins: Enhanced the auto-icon hack in PySide6 to use compatible class names. Standalone: Fix, Qt libraries were duplicated with PySide6 WebEngine framework support on macOS. Plugins: Fix, automatic detection of mypyc runtime dependencies was including all top level modules of the containing package by accident. (Fixed in 4.0.5 already.) Anaconda: Fix, delvewheel plugin was not working with Python 3.8+. This enhances compatibility with installed PyPI packages that use it for their DLLs. (Fixed in 4.0.6 already.) Plugins: Fix, our protection workaround could confuse methods used with PySide6. New Features UI: Added the --recommended-python-version option to display recommended Python versions for supported, working, or commercial usage. UI: Add message to inform users about Nuitka[onefile] if compression is not installed. (Added in 4.0.1 already.) UI: Add support for uv_build in the --project option. (Added in 4.0.1 already.) Onefile: Allow extra includes as well. (Added in 4.0.2 already.) UI: Add nuitka-project-set feature to define project variables, checking for collisions with reserved runtime variables. (Added in 4.0.2 already.) Scons: Added new option to select --reproducible builds or not. (Added in 4.0.6 already.) Python 3.10+: Added support for importlib.metadata.package_distributions(). (Added in 4.0.8 already.) Plugins: Added support for the multiprocessing forkserver context. (Added in 4.0.8 already, for 4.1 Python 3.6 and earlier, as well as 3.14 support were added too.) Reports: Added structured resource usage (rusage) performance information to compilation reports. Reports: Included individual module-level C compiler caching (ccache/clcache) statistics in compilation reports. Added support for detecting and correctly resolving the Python prefix for the PyEnv on Homebrew Python flavor. macOS: Added support for rusage information for Scons. UI: Added the __compiled__.extension_filename attribute to give the real filename of the containing extension module. Windows: Added support for --clang or ARM. (Added in 4.0.8 already.) Windows: Added support for resources names as not just integers, important when we copy them from template files. MacPorts: Added basic support for this Python flavor. More work will be needed to get it to work fully though. Optimization Avoid including importlib._bootstrap and importlib._bootstrap_external. (Added in 4.0.1 already.) Linux: Cached the syscall used for time keeping during compilation to avoid loading libc for each trace. (Added in 4.0.8 already.) UI: Output a warning for modules that remain unfinished after the third optimization pass. Added an extra micro pass trigger when new variables are introduced or variable usage changes severely, ensuring optimizations are fully propagated, avoiding unnecessary extra full passes. Provided scripts to compile Python statically with PGO tailored for Nuitka on Linux, Windows, and macOS. Added support for running the Data Composer tool from a compiled Nuitka binary without spawning an uncompiled Python process. Enhanced the usage of vectorcall for PyCFunction objects by directly checking for its presence instead of relying purely on flags, allowing more frequent use of this faster execution path. Cached frequently used declarations for top-level variables to speed up C code generation. Sped up trace collection merging by avoiding unnecessary set creation and using a set instead of a list for escaped traces. Optimized plugin hook execution by tracking overloaded methods and added an option to show plugin usage statistics. Improved performance of module location by avoiding unnecessary module name reconstruction and redundant filesystem checks for pre-loaded packages. Improved the caching of distribution name lookups to effectively avoid repeated IO operations across all package types. Plugins: Cached callback plugin dispatch for onFunctionBodyParsing and onClassBodyParsing to skip argument computation when no plugin overrides them. Python 3.13: Handled sub-packages of pathlib as hard modules. Handled hard attributes through merge traces as well. Made constant blobs more compact by avoiding repeated identifiers and unnecessary fields. Enhanced Python compilation scripts further. (Fixed in 4.0.8 already.) Recognized late incomplete variables better. (Fixed in 4.0.8 already.) Made constant blobs more compact. (Fixed in 4.0.8 already.) Optimized calls with only constant keywords and variable posargs too. Anti-Bloat Fix, memory bloat occurred when C compiling sqlalchemy. (Fixed in 4.0.2 already.) Avoid using pydoc in PySimpleGUI. (Added in 4.0.2 already.) Avoided using doctest from zodbpickle. (Added in 4.0.5 already.) Avoided inclusion of cython when using pyav. (Added in 4.0.7 already.) Avoided including typing_extensions when using numpy. (Added in 4.0.7 already.) Organizational UI: Relocated the warning about the available source code of extension modules to be evaluated at a more appropriate time. Debian: Remove recommendation for libfuse2 package as it is no longer useful. Debian: Used platformdirs instead of appdirs. Debugging: Removed Python 3.11+ restriction for clang-format as it is available everywhere, even Python 2.7, and we still want nicely formatted code when we read things. (Added in 4.0.6 already.) Removed no longer useful inline copy of wax_off. We have our own stubs generator project. Release: Added missing package to the CI container for building Nuitka Debian packages. Developer: Updated AI instructions for creating Minimal Reproducible Examples (MRE) to skip unneeded C compilation. Debugging: Added an internal function for checking if a string is a valid Python identifier. AI: Added a task in Visual Studio Code to export the currently selected Python interpreter path to a file, making it available as “python” and “pip” matching the selected interpreter. This makes it easier to use a specific version with no instructions needed. AI: Updated the rules to instruct AI to only generate useful comments that add context not present in the code. Containers: Added template rendering support for Jinja2 (.j2) container files in our internal Podman tools. Projects: Clarified the current status and rationale of Python 2.6 support in the developer manual. Debugging: Added experimental flag --experimental=ignore-extra-micro-pass to allow ignoring extra micro pass detection. Visual Code: Added integration scripts for bash and zsh autocompletion of Nuitka CLI options. These are now also integrated into Visual Studio Code terminal profiles and the Debian package. RPM: Included the Python compile script for Linux. RPM: Removed the requirement for distutils in the spec. Tests Install only necessary build tools for test cases. Avoided spurious failures in reference counting tests due to Python internal caching differences. (Fixed in 4.0.3 already.) Fix, the parsing of the compilation report for reflected tests was incorrect. Python 3.14: Ignored a syntax error message change. Python 3.14: Added test execution support options to the main test runner to use this version as well. Fix, the runner binary path was mishandled for the third pass of reflected compilations. Removed the usage of obsolete plugins in reflected compilation tests. Debugging: Prevented boolean testing of namedtuples to avoid unexpected bugs. Added the Test suffix to syntax test files and disabled “python” mode and spell checking for them to resolve issues reported in IDEs. Fix, newline handling in diff outputs from the output comparison tool was incorrect. Covered post-import-code functionality with a new subpackage test case. Prevented the program test suite from running an unnecessary variant to save execution time. macOS: Ignored differences from GUI framework error traces in headless runs in output comparisons. Reflected test for Nuitka, where it compiles itself and compares its operation has been restored to functional state. Used the new method to clear internal caches if available for reference counts. Disabled running nested loops test with Python 2.6. Containers: Detected Python 2 defaulting containers in Podman tooling. Cleanups UI: Fix, there was a double space in the Windows Runtime DLLs inclusion message. (Fixed in 4.0.1 already.) Onefile: Separated files and defines for extra includes for onefile boot and Python build. Scons: Provided nicer errors in case of “unset” variables being used, so we can tell it. Refactored the process execution results to correctly utilize our namedtuples variant, that makes it easier to understand what code does with the results. Quality: Enabled automatic conversion of em-dashes and en-dashes in code comments to the autoformat tool. AI won’t stop producing them and they can cause SyntaxError for older Python versions, nor is unnecessarily using UTF-8 welcome. Ensured that cloned outline nodes are assigned their correct names immediately upon creation, that avoids inconsistencies during their creation. Quality: Updated to the latest versions of black and adopted a faster isort execution by caching results. Quality: Modified the PyLint wrapper to exit gracefully instead of raising an error when no matching files require checking. Quality: Avoided checking YAML package configuration files twice, since autoformat already handles them. Quality: Ensured that YAML package configuration checks output the original filename instead of the temporary one when a failure occurs. Quality: Prevented pushing of tags from triggering git pre-push quality checks. Quality: Silenced the output of optipng and jpegoptim during image optimization auto-formatting. Visual Code: Added the generated Python alias path file to the ignore list. Quality: Enabled auto-formatting for the Nuitka devcontainer configuration file. Watch: Avoided absolute paths in compilation to make reports more comparable across machines. Quality: Changed mdformat checks to run only once and silently. Scons: Disabled format security errors in debug mode and moved Python-related warning disables into common build setup code. Quality: Updated to the latest deepdiff version. Scons: Avoided MSVC telemetry since it can produce outputs that break CI. Debugging: Enhanced non-deployment handler for importing excluded modules. Split import module finding functionality into more pieces for enhanced readability. Debugging: Added more assertions for constants loading and checking. macOS: Dropped the universal target arch. Debugging: Added more traces for deep hash verification. Summary This release builds on the scalability improvements established in 4.0, with enhanced Python 3.14 support, expanded package compatibility, and significant optimization work. The --project option seems usable now. Python 3.14 support remains experimental, but only barely made the cut, and probably will get there in hotfixes. Some of the corrections came in so late before the release, that it was just not possible to feel good about declaring it fully supported just yet.

23.05.2026 22:00:00

Informační Technologie
2 dny

We need volunteers to make EuroPython 2026 happen. And you might be exactly who we&aposre looking for!Before sharing all the information, here is a personal story from me: The first time I attended EuroPython in-person was as a volunteer. It was the first year after Covid, and I was nervous about traveling abroad for a conference where I didn&apost know anyone personally; there were only friendly faces from the previous year of volunteering online. When I volunteered online, it was easier. I could stay in my comfort zone. But stepping out of that zone to meet people face-to-face? That changed everything 🐍❤️ Those online faces became really good friends. Now I want to go for every EuroPython because I will get to meet them again. Volunteering with friends became such fun I didn&apost even notice that I was constantly stepping outside my comfort zone 💃 So, if you&aposre thinking of volunteering, just do it! You will meet awesome humans and have fun while helping people surrounded by positive vibes 💖 As a volunteer, you&aposre the face of the conference. Your job is to make sure everyone has a great time. We need volunteers to be welcoming, helpful, and collaborative; making sure everyone (including yourself) is comfortable and happy.There are lots of different ways to help, depending on your interests and availability:Registration Desk: Check in attendees, hand out badges, answer questionsT-Shirt Handout: Hand out awesome EuroPython merch to attendeesRoom Manager: Keep things running smoothly in talk rooms, ensure speakers are readySession Chair: Introduce speakers, manage transitions, signal time, handle Q&AGreeter / Badge Check: Welcome people, check for badges at entryRunners: Help with whatever is needed at the moment! You can sign up for as many or as few slots as you want. Even a couple of hours helps. We&aposd appreciate it if you could do more than one, but no pressure, whatever you can give is valuable.In the volunteering form, tell us what sounds interesting. Get matched with a role that fits your skills and availability. Show up, help out, and be part of something amazing.That&aposs it. No experience necessary. You don&apost need to be a Python expert. You just need to care about the community and be willing to help out. Whether that&aposs greeting people at the door, managing the schedule, troubleshooting tech issues, or making sure speakers have what they need - we have a place for you.What do you get?🎫 Free Ticket if you dedicate 10 hours or more (Tutorials + Conference)👕Volunteer T-Shirt: Awesome EuroPython merch to keep and show off⭐ <3 Forever: Featured on the EuroPython 2026 Team pageCheck out this page for all the details, including descriptions of various roles: https://ep2026.europython.eu/volunteering/Sign Up To VolunteerAnd if you have more questions? Just reach out volunteers@europython.eu. We&aposre here to help.🎁 Sponsor SpotlightWe&aposd like to thank Manychat for sponsoring EuroPython.Manychat builds AI-powered chat automation for 1M+ creators and brands at real production scale.👋 Stay ConnectedFollow us on social media and subscribe to our newsletter for all the updates:👉 Sign up for the newsletter: https://blog.europython.eu/portal/signupLinkedIn: https://www.linkedin.com/company/europython/X/Twitter: https://x.com/europythonMastodon: https://fosstodon.org/@europythonBluesky: https://bsky.app/profile/europython.euInstagram: https://www.instagram.com/europython/YouTube: https://www.youtube.com/@EuroPythonConferenceHopefully, we’ll see you on this side soon 🔜 😉Cheers,Sangarshanan Veera, EuroPython 2026 Communications Team Sign up for EuroPython Blog The official blog of everything & anything EuroPython! EuroPython 2026 13-19 July, Kraków Subscribe .nc-loop-dots-4-24-icon-o{--animation-duration:0.8s} .nc-loop-dots-4-24-icon-o *{opacity:.4;transform:scale(.75);animation:nc-loop-dots-4-anim var(--animation-duration) infinite} .nc-loop-dots-4-24-icon-o :nth-child(1){transform-origin:4px 12px;animation-delay:-.3s;animation-delay:calc(var(--animation-duration)/-2.666)} .nc-loop-dots-4-24-icon-o :nth-child(2){transform-origin:12px 12px;animation-delay:-.15s;animation-delay:calc(var(--animation-duration)/-5.333)} .nc-loop-dots-4-24-icon-o :nth-child(3){transform-origin:20px 12px} @keyframes nc-loop-dots-4-anim{0%,100%{opacity:.4;transform:scale(.75)}50%{opacity:1;transform:scale(1)}} Email sent! Check your inbox to complete your signup. No spam. Unsubscribe anytime.

23.05.2026 07:00:34

Informační Technologie
3 dny

The trickiest programming bugs are often caused by catching exceptions that you didn't mean to catch or handling exceptions in ways that **obfuscate the actual error that's occurring. Which exceptions should you catch and which should you leave unhandled? Table of contents Catching many exceptions at once When will a NameError be raised? When will a ValueError be raised? When will a TypeError be raised? When will a KeyError be raised? Handling problems preemptively When should you catch all possible types of exceptions? Summary Catching many exceptions at once When catching an exception, it's generally considered a good idea to only catch exceptions if you understand their origin. Here we have some code that catches many exception types at once. We're catching a ValueError, a TypeError, a KeyError, and a NameError exception: import csv import datetime import sys def parse_date(date_string): return datetime.date.fromisoformat(date_string) [filename] = sys.argv[1:] with open(filename) as csv_file: reader = csv.DictReader(csv_file) for n, row in enumerate(reader, start=1): name = row["name"] try: start, end = parse_date(row["start"]), parse_date(row["end"]) except (ValueError, TypeError, KeyError, NameError) as e: error = type(e).__name__ print(f"{error}: Invalid date on line {n}", file=sys.stderr) continue time = end - start print(f"{name}: {time.days} days") It's not entirely clear why it catches each of these types of exceptions. When will a NameError be raised? We probably shouldn't be catching … Read the full article: https://www.pythonmorsels.com/what-types-of-exceptions-should-you-catch/

22.05.2026 17:45:00

Informační Technologie
3 dny

Let’s say you’re writing a Python library. In this library, you have some collection of state that represents “options” or “configuration” for a bunch of operations. Such a set of options is a bundle of potentially ever-increasing complexity. Thus, you will want it to have an extremely minimal compatibility surface, with a very carefully chosen public interface, that is either small, or perhaps nothing at all. Such an object conveys state and might have some private behavior, but all you want consumers to be able to do is build it in very constrained, specific ways, and then pass it along as a parameter to your own APIs. By way of example, imagine that you’re wrapping a library that handles shipping physical packages. There are a zillion ways to do it ship a package. There are different carriers who can ship it for you. There’s air freight, and ground freight, and sea freight. There’s overnight shipping. There’s the option to require a signature. There’s package tracking and certified mail. Suffice it to say, lots of stuff. If you are starting out to implement such a library, you might need an object called something like ShippingOptions that encapsulates some of this. At the core of your library you might have a function like this: 1 2 3 4 5async def shipPackage( how: ShippingOptions, where: Address, ) -> ShippingStatus: ... If you are starting out implementing such a library, you know that you’re going to get the initial implementation of ShippingOptions wrong; or, at the very least, if not “wrong”, then “incomplete”. You should not want to commit to an expansive public API with a ton of different attributes until you really understand the problem domain pretty well. Yet, ShippingOptions is absolutely vital to the rest of your library. You’ll need to construct it and pass it to various methods like estimateShippingCost and shipPackage. So you’re not going to want a ton of complexity and churn as you evolve it to be more complex. Worse yet, this object has to hold a ton of state. It’s got attributes, maybe even quite complex internal attributes that relate to different shipping services. Right now, today, you need to add something so you can have “no rush”, “standard” and “expedited” options. You can’t just put off implementing that indefinitely until you can come up with the perfect shape. What to do? The tool you want here is the opaque data type design pattern. C is lousy with such things (FILE, pthread_*_t, fd_set, etc). A typedef in a header file can easily achieve this. But in Python, if you expose a dataclass — or any class, really — even if you keep all your fields private, the constructor is still, inherently, public. You can make it raise an exception or something, but your type checker still won’t help your users; it’ll still look like it’s a normal class. Luckily, Python typing provides a tool for this: typing.NewType. Let’s review our requirements: We need a type that our client code can use in its type annotations; it needs to be public. They need to be able to consruct it somehow, even if they shouldn’t be able to see its attributes or its internal constructor arguments. To express high-level things (like “ship fast”) that should stay supported as we add more nuanced and complex configurations in the future (like “ship with the fastest possible option provided by the lowest-cost carrier that supports signature verification”). In order to solve these problems respectively, we will use: a public NewType, which gives us our public name... which wraps a private class with entirely private attributes, to give us an actual data structure, while not exposing the constructor, a set of public constructor functions, which returns our NewType. When we put that all together, it looks like this: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17from dataclasses import dataclass from typing import Literal, NewType @dataclass class _RealShipOpts: _speed: Literal["fast", "normal", "slow"] ShippingOptions = NewType("ShippingOptions", _RealShipOpts) def shipFast() -> ShippingOptions: return ShippingOptions(_RealShipOpts("fast")) def shipNormal() -> ShippingOptions: return ShippingOptions(_RealShipOpts("normal")) def shipSlow() -> ShippingOptions: return ShippingOptions(_RealShipOpts("slow")) As a snapshot in time, this is not all that interesting; we could have just exposed _RealShipOpts as a public class and saved ourselves some time. The fact that this exposes a constructor that takes a string is not a big deal for the present moment. For an initial quick and dirty implementation, we can just do checks like if options._speed == "fast" in our shipping and estimation code. However, the main thing we are doing here is preserving our flexibility to evolve the related APIs into the future, so let’s see how we might do that. For example, let’s allow the shipping options to contain a concrete and specific carrier and freight method: 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 35from dataclasses import dataclass from enum import Enum, auto from typing import NewType class Carrier(Enum): FedEx = auto() USPS = auto() DHL = auto() UPS = auto() class Conveyance(Enum): air = auto() truck = auto() train = auto() @dataclass class _RealShipOpts: _carrier: Carrier _freight: Conveyance ShippingOptions = NewType("ShippingOptions", _RealShipOpts) def shipFast() -> ShippingOptions: return ShippingOptions(_RealShipOpts(Carrier.FedEx, Conveyance.air)) def shipNormal() -> ShippingOptions: return ShippingOptions(_RealShipOpts(Carrier.UPS, Conveyance.truck)) def shipSlow() -> ShippingOptions: return ShippingOptions(_RealShipOpts(Carrier.USPS, Conveyance.train)) def shippingDetailed( carrier: Carrier, conveyance: Conveyance ) -> ShippingOptions: return ShippingOptions(_RealShipOpts(carrier, conveyance)) As a NewType, our public ShippingOptions type doesn’t have a constructor. Since _RealShipOpts is private, and all its attributes are private, we can completely remove the old versions. Anything within our shipping library can still access the private variables on ShippingOptions; as a NewType, it’s the same type as its base at runtime, so it presents minimal1 overhead. Clients outside our shipping library can still call all of our public constructors: shipFast, shipNormal, and shipSlow all still work with the same (as far as calling code knows) signature and behavior. If you need to build and convey some state within your public API, while avoiding breakages associated with compatibility churn, hopefully this technique can help you do that! Acknowledgments Thanks for reading, and thank you to my patrons who are supporting my writing on this blog. If you like what you’ve read here and you’d like to read more of it, or you’d like to support my various open-source endeavors, you can support my work as a sponsor. The overhead is minimal, but it is not completely zero. The suggested idiom for converting to a NewType is to call it like a function, as I’ve done in these examples, but if you are wanting to use this pattern inside of a hot loop, you can use # type: ignore[return-value] comments to avoid that small cost. ↩

22.05.2026 00:33:00

Informační Technologie
3 dny

Most "AI agents" shipping right now are demos wearing production paint. They answer questions fluently and break the moment they touch a workflow with money, state, or consequences. The agent illusion Multi-agent frameworks benchmark beautifully. Five specialist LLMs cooperate, the demo plays cleanly, the README has a diagram with arrows. Then someone wires the thing to a real billing system and it issues three refunds for the same chargeback because a tool call retried on a flaky network. That gap is the actual job most agent tutorials skip. When I review AI code, the same pattern keeps appearing. The LLM call is fine. The agent loop is fine. What is missing is the layer underneath: state, idempotency, audit, and a tool surface the agent cannot use to hurt you. The unsexy layer Systems answer four questions before the agent does anything: What did the agent already do? Persisted state, not "look at the conversation history." What happens if this action runs twice? Idempotency keys on every external effect. Who approved this? An audit log a human can read during a postmortem. Can I roll this back? A clear inverse for every irreversible operation, or a freeze before execution. None of this is glamorous. It is also what separates a system that is a toy demo from one that can run mostly unsupervised in production. The shape of that contract in code: class ExpenseAction(BaseModel): idempotency_key: str requested_by: str requested_at: datetime approval_required: bool = True dry_run: bool = True payload: ExpensePayload def submit(action: ExpenseAction, repo: ExpenseRepo) -> Result: if repo.find_by_key(action.idempotency_key): return Result.duplicate() if action.dry_run: return Result.preview(action.plan()) if action.approval_required and not action.is_approved(): return Result.pending_approval() repo.persist(action) return Result.ok(action.execute()) The agent does not call the side effect. It builds a typed plan. A function decides whether to run it. State that survives retries Agents need state management that works across restarts and network failures. The Telegram expense bot we build in our Agentic AI cohort program, uses context.user_data to track multi-step flows: async def handle_expense_text(self, update, context): text = update.message.text result = self._preprocessor.preprocess(text) if not result.is_valid: await update.message.reply_text(f"Invalid: {result.error}") return ConversationHandler.END response = self._build_service().classify(result.text).response # Store state for the callback handler context.user_data["expense_description"] = result.text context.user_data["classification_response"] = response keyboard = build_category_confirmation_keyboard( suggested_category=response.category, all_categories=[c.value for c in ExpenseCategory], ) await update.message.reply_text( f"I categorized this as {response.category} ({response.total_amount} {response.currency}). Confirm or pick another category:", reply_markup=keyboard, ) return ConversationState.WAITING_FOR_CATEGORY async def handle_category_selection(self, update, context): query = update.callback_query await query.answer() # Retrieve state from previous handler description = context.user_data.get("expense_description") response = context.user_data.get("classification_response") if description is None or response is None: await query.edit_message_text("Session expired. Send expense again.") return ConversationHandler.END _, category = query.data.split(":", 1) self._build_service().persist_with_category( expense_description=description, category_name=category, response=response, telegram_user_id=update.effective_user.id, ) await query.edit_message_text(f"Saved as {category}!") return ConversationHandler.END The .get() with defensive error handling is what saves you when the bot restarts mid-conversation. No silent corruption, no half-written database rows. The user just has to resend their expense description and pick the category again. This is the work of production agents. Tools the agent cannot trust LLMs are undeterministic and hallucinate. Design your tool surface for mistrust: Narrow scopes. read_expense and flag_expense are two tools, not one tool with a mode flag the LLM can flip. Dry-run by default. Every write tool returns a plan first. The agent opts in to execute. You get human-in-the-loop (HITL) for free. Schema-validated inputs. Pydantic at the tool boundary so a malformed argument cannot reach your database. Explicit confirmation for anything destructive. The agent proposes, a human taps approve. The agent is not the brain of your application. It is a planner that we acknowledge is fallible. The real logic lives in the tools, and the agent's job is to call them with valid inputs and ask for help when it is unsure. Input validation before the LLM sees anything Validate at system boundaries before user input reaches your tools. This prevents XSS, length attacks, and malformed data from consuming tokens: from dataclasses import dataclass, field import re XSS_PATTERNS = ("<script", "javascript:", "onerror=", "onload=") CURRENCY_SYMBOLS = {"$": "USD", "€": "EUR", "£": "GBP", "¥": "JPY"} AMOUNT_PATTERN = re.compile(r"\d+([.,]\d+)?") @dataclass class PreprocessingResult: text: str is_valid: bool warnings: list[str] = field(default_factory=list) error: str | None = None class InputPreprocessor: def preprocess(self, text: str) -> PreprocessingResult: text = text.strip() if len(text) < 3: return PreprocessingResult(text, False, error="Input too short") if len(text) > 500: return PreprocessingResult(text, False, error="Input too long") if any(pattern in text.lower() for pattern in XSS_PATTERNS): return PreprocessingResult(text, False, error="Invalid characters") for symbol, code in CURRENCY_SYMBOLS.items(): text = text.replace(symbol, code) warnings = [] if not AMOUNT_PATTERN.search(text): warnings.append("No amount detected") return PreprocessingResult(text, True, warnings) This runs before the LLM call, returning error messages without burning tokens or risking injection. Human-in-the-loop as a design pattern Production agents are not fully autonomous. They classify, extract, or suggest, then wait for a human to confirm. Confidence scores guide when to ask: from dataclasses import dataclass @dataclass(frozen=True) class ClassificationResult: response: ExpenseCategorizationResponse persisted: bool def process_with_hitl(result: ClassificationResult, threshold: float = 0.8) -> str: if result.response.confidence >= threshold: return result.response.category print( f"Low confidence ({result.response.confidence:.0%}): '{result.response.category}' — {result.response.reason}" ) user_input = input( f"Accept '{result.response.category}'? (Enter to confirm, or type a category): " ).strip() if not user_input: return result.response.category return user_input In the Telegram bot, this becomes an inline keyboard. The bot states its category guess and asks the human to confirm or pick a different one, with the AI suggestion highlighted. The pattern: AI proposes, human disposes. This surfaces in the service layer we built in prior weeks: @dataclass class ClassificationService: assistant: Assistant expense_repo: ExpenseRepository def classify(self, description: str) -> ClassificationResult: messages = self._build_messages(description) response = self.assistant.completion(messages) return ClassificationResult(response=response, persisted=False) def persist_with_category( self, expense_description: str, category_name: str, response: ExpenseCategorizationResponse, telegram_user_id: int | None = None, ) -> None: """Store the user's chosen category, not the AI guess.""" expense = Expense( amount=response.total_amount, currency=response.currency, category=ExpenseCategory(category_name), description=expense_description, telegram_user_id=telegram_user_id, ) self.expense_repo.add(expense) The persist_with_category method accepts the human's decision. The database stores what the user confirmed, not what the model guessed. As the ExpenseCategorizationResponse captures the AI's original category and confidence, we can analyze overrides later to identify model weaknesses. Dependency injection for testable agents The service layer pattern separates business logic from LLM provider details. Inject dependencies rather than hardcoding them: from unittest.mock import create_autospec from decimal import Decimal def test_classify_calls_assistant(): # No real OpenAI call, no .env file, no network mock_assistant = create_autospec(Assistant) mock_assistant.completion.return_value = ExpenseCategorizationResponse( category="Food", total_amount=Decimal("5.50"), currency=Currency.USD, confidence=0.95, cost=Decimal("0.001"), ) mock_repo = create_autospec(ExpenseRepository) service = ClassificationService(assistant=mock_assistant, expense_repo=mock_repo) result = service.classify("Coffee at Starbucks $5.50") mock_assistant.completion.assert_called_once() assert result.response.category == "Food" assert result.persisted is False Because the service receives its dependencies rather than creating them, you can test classification logic without burning API credits or waiting on network calls. This is a key strategy to test the interface at the service layer, not the LLM provider. The same service powers the CLI, Telegram bot, and REST API. Change providers (OpenAI to Anthropic) or add caching by swapping the Assistant implementation. Business logic stays untouched. Speed vs safety The tradeoff is iteration speed vs execution safety. Put the LLM behind a typed service boundary and you can swap models without touching business logic. Store actions as events instead of overwriting state, and your audit log writes itself. I wrote about why event sourcing pays off. Agentic loops with typed tool results The tool-use loop needs to handle partial results, retries, and tool failures. Here is the pattern from the warm up exercises you can do on our Agentic Cohort page: from typing import cast import anthropic from anthropic.types import ( MessageParam, TextBlock, ToolUseBlock, ToolResultBlockParam, ) # TOOLS defined with JSON schema for get_exchange_rate(from_currency, to_currency) def answer_with_tools(question: str, client: anthropic.Anthropic) -> str: messages: list[MessageParam] = [{"role": "user", "content": question}] while True: response = client.messages.create( model="claude-sonnet-4-6", max_tokens=512, tools=TOOLS, messages=messages, ) if response.stop_reason == "end_turn": return cast(TextBlock, response.content[0]).text if response.stop_reason != "tool_use": # anything other than tool_use here means no tool calls to process — looping would spin forever raise RuntimeError(f"Unexpected stop reason: {response.stop_reason}") tool_uses = [ cast(ToolUseBlock, b) for b in response.content if b.type == "tool_use" ] tool_results: list[ToolResultBlockParam] = [ { "type": "tool_result", "tool_use_id": b.id, "content": str(get_exchange_rate(**cast(dict[str, str], b.input))), } for b in tool_uses ] messages.append({"role": "assistant", "content": response.content}) messages.append({"role": "user", "content": tool_results}) The loop continues until stop_reason == "end_turn". Tool results are typed, preventing schema drift between the tool definition and implementation. In production, wrap get_exchange_rate() in a try/except and return error results to the LLM when tools fail. The agent can retry, pick a different tool, or surface the error to the user. The fix is separation of concerns, typed interfaces, and a well-defined contract between the agent and its tools. Keep reading How an AI expense agent is actually structured Build the data layer before you touch the LLM Stop prompting, start structuring your AI workflow

22.05.2026 00:00:00

Informační Technologie
4 dny

I know how I like to learn new things. Over the years, I figured out what works for me and what doesn’t. If you read my articles or attend my courses, then you know how I like to learn since I teach in the same way.The challenge when learning something new is finding resources that are just right for me. And that’s not easy. I know I can learn things better and quicker with resources that fit my style well, but you can’t always find these resources.I recently got particularly annoyed learning about the biomechanics of sprinting – I do have non-Python interests, yes – because all three textbooks I read, and lots of the online writing in this field, are just, let’s say, not great.But I now found the solution.After many decades of learning in the same way, I have now upgraded how I learn thanks to my new tutor, Priya.Yes, I gave her a name. No, she’s not a real person. Priya is my personalised tutor agent. I’ll tell you all about her below.And you’ll experience her teaching, too (not on the Python articles, though, I’ll keep writing those the old-fashioned way.) I’ll tell you more about this below, too, but let me first tell you why this works for me.My Tutor, My StyleI’ve been thinking about the way I learn and teach for many years, from way back when I was a young University lecturer faced with 120 students in a lecture hall. I wasn’t that much older than the students, but I learnt fast. And they liked my teaching (I even have awards to prove it!)More recently, I’ve been writing a lot. I wrote articles here on The Python Coding Stack and elsewhere. I wrote a Python textbook. I even wrote about learning and technical writing in Breaking the Rules: the substack and the book.All this meant that I could ask my freshly-spawned agent to spend a bit of time reading what I wrote to understand how I teach, which is how I like to learn. Priya analysed the techniques I use in my writing and understood my motivations for doing what I do through my technical writing texts.Then, Priya and I had a good chat to refine ideas, to make sure she captured the essence of “my style”.And since Priya is an AI agent, “my style” became her knowledge base. This knowledge now lives in several lengthy markdown files and is summarised in shorter context packs and an index to ensure Priya’s short-term memory (the context window) isn’t overwhelmed.Then I was ready to go. Any topic I wanted to learn, large or small, I could ask Priya to research it thoroughly, creating a new set of knowledge files, this time specific to the topic she needed to teach rather than my learning style. And then, she’s ready to teach me.And it worked. The stuff she prepared was exactly the way I like it.The Tutor-Student Conversation CourseAnd here’s the format I settled on (for now). Once the agent completes her research about the topic I want to learn, I ask her to plan a course spanning several modules.But here’s the refinement loop that makes the real difference:I ask Priya to draft the first module. She writes this in a markdown file.I read through her draft and leave comments and questions directly within the text.Priya reads my questions and revises the text to address my questions. (But read on to find out more about the two categories of comments/questions I leave for her.)Repeat steps 2 and 3 until I feel I understand the topic.Move on to the next module and repeat steps 1 to 4.This is a human-in-the-loop approach to creating the learning material. Yes, Priya is trained in my way of learning and teaching and in my writing style. But I’m actively having a conversation with her within the text.This is equivalent to raising your hand in a lesson and asking the teacher a question. A good teacher will then revise how they present the material to address your question.Priya’s learning materials are just like that. In fact, I will take credit for her output. Sure, I’m not an expert in the subject matter she’s teaching me – that’s the whole point, right? But the output reflects my views and ideas about teaching and includes my questions and queries as I tried to understand and master the topic.This is a collaboration. Priya and I are co-authors, even though Priya did most of the “writing”.I tried this approach on several topics, but there are two I want to share with you. I’m setting up two new sections here on The Python Coding Stack, which I’ll use to learn these two topics in public. I’ll publish the “transcripts” of the conversations Priya and I are having. It’s mostly Priya doing the talking, but my questions are there, too.The first topic I’m learning in public with Priya’s help is Agentic AI. It’s very meta to use agentic AI to learn about agentic AI! I’ll publish an introduction and the first module in the coming days in the new section here on The Python Coding Stack called Agents Unpacked. You can already see this section in the menu on the homepage.I’ll set up another section to deal with the second topic in a week or so. No spoilers for now except to say it’s directly related to programming but it’s distinct from the articles I publish in the main section on The Python Coding Stack and in The Club.By the way, you’ll be able to select which sections you want to receive regularly by email. So if you’re interested in my Python core content but not in these other topics, you can pick and choose what to opt out of. You can always go to The Python Coding Stack to read the other sections, of course.How Priya and I Create These “Courses”But let me expand on how Priya – my tutor agent – and I created these courses. [Incidentally, those are my em-dashes – I use them often and have always done. Commas would be ambiguous in that context!]I provide two types of questions or comments to my agent as I read through the drafts: private and public.Private Questions and CommentsWhen Priya reads the private questions or comments, she makes changes to the text, but then she deletes my input. So, you won’t see my intervention explicitly in these cases. However, Priya’s text reflects my thoughts. My interventions guide Priya. This type of intervention is similar to an editor’s role, but I’m intervening as a learner more than as an editor.Public Questions and CommentsHowever, when Priya comes across a comment or question I mark as public, she leaves it in the text, acknowledges the question, and answers it directly. So, you’ll see my public questions in the text. Priya and I decided not to include too many of these public questions to keep the text flowing. However, I think it’s beneficial to see some of my interventions. My questions may also be your questions.More Learning. More Articles. More FunAs with everything to do with AI, this is all very new. It’s a work in progress. I may refine and revise how I interact with my agent. But it’s been fun learning this way, and I hope you enjoy reading my interactions with Priya and you find it useful, too.To state the obvious, the posts I’ll publish in these two new sections are mostly AI-generated content. If you read this far, then you won’t be surprised by that statement. A year ago, I would never have thought I’d publish anything written by AI. But a year is a long time in the AI world. And this AI content reflects me and my thinking. The agent is my mentee – someone I trained to teach the way I do, to write the way I do. But she’s also my tutor, teaching me new stuff.So there’s a lot of “me” in what you read, even if it’s mostly written by Priya!The posts in the main section of The Python Coding Place and those in The Club (for premium subscribers) won’t change. They’re still my writing from beginning to end. Every word and letter you read in those posts is the result of nerve signals going from my brain to my fingers, which tap keys on a keyboard. In this era of AI doing a lot of work for us, I think it’s more important than ever for me to keep using my pre-AI skills. Otherwise, my brain will atrophy, and I don’t want that!So, in summary, there will soon be four sections here on The Stack:The main area in The Python Coding Stack – no change here, you’ll get the same type of Python articles you’ve been reading for the past 3+ yearsThe Club – the extra Python posts for premium subscribersAgents Unpacked – the Agentic AI course Priya and I are creating for me to learn all about this agentic stuff. Learn with me (and Priya) if you’re interested.Mystery Fourth Section – Stay tuned, you won’t have to wait long. This is also a Priya-Stephen collaboration.Next post will be the introduction and first section in Agents Unpacked. Soon after, I have another Python post I’m planning for you.Subscribe nowstephengruppetta.comPhoto by detait

21.05.2026 21:23:09

Informační Technologie
4 dny

UPDATE May 22, 2026: This article hit the Hacker News front page. Readers pointed out a couple of things I’d missed and one bit of framing I should have been clearer about. See the Corrections and clarifications section at the bottom. Astral’s uv has taken the Python world by storm, and for good reason. It is blisteringly fast, handles Python versions with ease, and replaces a half-dozen tools with a single binary. I’ve written multiple articles about it before. Getting started with a new Python project using uv and adding your first dependencies is very easy. But once you move past the initial setup and into the maintenance phase of a project, i.e. checking for outdated packages and performing routine upgrades, the CLI starts to feel surprisingly clunky compared to its peers like pnpm or Poetry. Finding outdated packages In my JavaScript projects, if I want to see what needs an update, I run: $ pnpm outdated This gives a clean, concise list of outdated packages, their current version, the latest version, and the version allowed by your constraints. In uv, there is no uv outdated. Instead, you have to memorize the following mouthful: $ uv tree --outdated --depth 1 The output is also a problem. It doesn’t just show you what is outdated; it shows you your entire top-level dependency tree, with a small annotation next to the ones that have updates available. If you have 50 dependencies and only two are outdated, you still have to scan a 50-line list. Poetry isn’t much better with its command poetry show --outdated, but at least it only shows actual outdated packages. Unsafe version constraints by default This is the most significant philosophical departure uv takes from pnpm and Poetry, and it’s a dangerous one for production stability. How pnpm/Poetry handle it When you add a package using pnpm add, it writes it to package.json using the caret requirement (^1.23.4). The caret at the beginning means that any 1.x.x version is allowed, but it will not update to 2.0.0. Poetry does the same by default, using a format like >=1.23.4,<2.0.0. I find this less readable than ^1.23.4, but the effect is the same. In both cases, updates are safe by default. You can run pnpm update or poetry update every morning and have high confidence that your build won’t break due to a major API change (assuming the packages you depend on respect SemVer). How uv handles it When you run uv add pydantic, it inserts this into your pyproject.toml: dependencies = [ "pydantic>=2.13.4", ] Note the lack of an upper bound. In the eyes of uv, pydantic version 2, 3, and 100 are all perfectly acceptable. This means uv updates are unsafe by default. If you run a bulk update, you aren’t just getting bug fixes; you are opting into every breaking change published by every maintainer in your dependency graph. The bad UX of the upgrade command The commands to actually perform an update in uv feel like they were designed for machines rather than humans. If you want to update everything in pnpm or Poetry, it’s a simple pnpm update or poetry update command. In uv, you use: $ uv lock --upgrade THOUGHTS Why isn’t this simply uv update or uv upgrade? Who designed this command line interface? It’s not uv lock --add or uv lock --remove either! Because of the “no upper bounds” issue mentioned above, uv lock --upgrade is a nuclear option. It will upgrade every single package in your lockfile to their absolute latest versions, ignoring SemVer safety. And this includes deep, nested dependencies you’ve never heard of! Good luck, better hope there are no breaking changes anywhere. Once you realize this is too risky, you’ll want to upgrade only specific packages. After scouring the subpar output of uv tree --outdated --depth 1 to find them, the syntax becomes a repetitive chore. How pnpm does it: $ pnpm update pydantic httpx uvicorn How uv does it: $ uv lock --upgrade-package pydantic --upgrade-package httpx --upgrade-package uvicorn Having to repeat the --upgrade-package flag for every single item is a huge hassle when you want to update a bunch of packages. I don’t understand why the UX of uv’s commands is so poor. There is hope: the bounds flag Luckily uv has recently introduced a --bounds option for uv add: $ uv add pydantic --bounds major This produces the safer pydantic>=2.13.4,<3.0.0 constraint we’ve come to expect. However, this is currently an opt-in feature. You have to remember to type it every time, and as of now, it is considered a preview feature. Until --bounds major (or a similar configuration) becomes the default behavior, uv users are essentially forced to choose between two bad options: Manually edit pyproject.toml to add upper bounds for every single dependency. Live in fear that uv lock --upgrade will accidentally pull in a breaking major version change. What I’d like to see I love uv. Its speed is transformative, and the way it manages Python toolchains is second to none. But as a package manager, the developer experience for maintaining a project is currently a step backward from the tools that came before it. We need a dedicated uv outdated command that filters noise, a more ergonomic update command that doesn’t require repeating flags, and default version constraints that respect the sanity of Semantic Versioning. Until then, I’ll be double-checking every single line of my lockfile changes with a healthy dose of suspicion. Corrections and clarifications After this article hit Hacker News, readers pointed out two things I’d missed and one bit of framing I should have been clearer about up front. Use uv pip list --outdated instead of uv tree --outdated --depth 1. The uv pip command actually filters to only outdated packages, which makes the “Finding outdated packages” critique much weaker than I made it out to be. The remaining complaint is that this lives under the pip-compatibility namespace rather than as a first-class top-level command, which is a discoverability issue, not a noisy-output one. You can set the --bounds default in pyproject.toml. You don’t have to remember to type --bounds major on every uv add. You can set it once: [tool.uv] add-bounds = "major" This invalidates the “two bad options” framing in the bounds-flag section. The actual situation is closer to: set this once in your config, and you get sensible defaults from then on. It’s still a preview feature, and for applications it would be better as the default, but the ergonomics are not nearly as bad as I painted them. Scope: applications vs. libraries. The standard Python packaging advice is that libraries published to PyPI should not pin upper bounds, and that advice is correct. If every library pins upper bounds, downstream consumers end up with dependency trees that can’t resolve. But for applications, where you are the terminal node in the dependency graph and nobody resolves against your constraints, the calculus is reversed: upper bounds cost you nothing and protect you from surprise major version bumps. This article is about maintaining applications (websites, services, internal tools), not publishing libraries. I should have been explicit about that from the start, because the “no upper bounds” default is indeed reasonable for the library case.

21.05.2026 18:08:41

Informační Technologie
4 dny

Making software accessible often comes down to removing small but repeated points of friction in everyday workflows. Today, on Global Accessibility Awareness Day, we‚Äôre sharing recent improvements in JetBrains IDEs across several areas: compatibility with assistive technologies on various platforms, keyboard navigation, and non-visual feedback. Some of these improvements are already available, and some are coming later this year. You can use the audio player below to listen to this blog post. Accessibility Blog Post Audio Better compatibility with assistive technologies One of the key areas we‚Äôve been working on is improving how JetBrains IDEs interact with OS-level accessibility tools. Improved Magnifier support on Windows Screen magnifiers are among the most commonly used assistive technologies in JetBrains IDEs. Until recently, the built-in Windows Magnifier didn‚Äôt reliably follow the text cursor in the editor, making navigation and editing more difficult for low-vision users. We‚Äôve implemented support for cursor tracking so Magnifier follows text as you type, just as it does in other applications. This builds on earlier work on macOS, where we addressed text cursor tracking with macOS Zoom. Now, the same support is being extended to Windows. Orca and GNOME Magnifier support on Linux With version 2026.2, coming this summer, JetBrains IDEs will allow you to use the Orca screen reader and GNOME Magnifier in supported Linux environments.  This is an active area of work, with multiple related tasks already underway. Accessibility shouldn‚Äôt depend on your operating system, and we‚Äôre continuing to improve support across platforms. More predictable keyboard navigation We‚Äôve also been making it easier to move through the IDE without relying on a mouse. Main menu access with Alt on Windows In native Windows applications, pressing Alt moves the focus to the main menu, allowing you to navigate it with the keyboard. This behavior was previously missing from JetBrains IDEs, and screen readers, such as NVDA, would sometimes announce the system menu instead. Now, the main menu behaves in a way that feels familiar and predictable for keyboard-only and screen-reader users, and the bright focus indicator helps low-vision users identify the selected item.   Navigating between major parts of the IDE Another focus area is the experience of moving between different parts of the IDE interface, such as toolbars, panels, and the editor. We‚Äôre working on a more structured model for navigating through the big component groups: Tab and Shift+Tab move the focus within the current area. A dedicated shortcut lets you jump between larger sections of the IDE. This reduces the effort required to reach essential controls and makes the overall layout easier to navigate. For the current iteration, we made it possible to bring the main toolbar and status bar into focus, and we fixed the Project and Git toolbar widgets, which were not selectable by screen readers, even though other elements already were.  As the next step, we‚Äôll polish specific controls and include tool window bars on both sides of the IDE frame in the navigation flow. Exploring richer non-visual feedback with audio cues Accessibility is not only about reaching controls, but also about understanding what‚Äôs happening while you work. We‚Äôre exploring ways to provide richer audio feedback in the IDE. Two directions we‚Äôre currently investigating: Contextual signals when the caret lands on lines with errors, warnings, breakpoints, or version control changes. We want the IDE to provide immediate, non-visual feedback in context. More general audio notifications for IDE actions and state changes. The goal is to reduce the need to rely on visual indicators or switch contexts just to understand what changed. Instead, we want the IDE to provide that information more directly. Accessibility as an ongoing effort We‚Äôre improving accessibility in JetBrains IDEs across multiple areas at once, including by providing compatibility with assistive technologies like screen readers and magnifiers, as well as by offering more consistent keyboard navigation and clearer feedback for events that are otherwise mostly visual. These improvements build on earlier updates, such as support for VoiceOver and NVDA, a high-contrast UI theme, and color schemes for red-green vision deficiency. There‚Äôs still more to do, and we‚Äôll continue working in this direction. We‚Äôd love to hear from you We‚Äôre eager to hear from developers who rely on accessibility features, as well as from anyone interested in improving the experience of using them. If you have ideas or feedback about accessibility in JetBrains IDEs, you can reach us directly at accessibility@jetbrains.com. You can also report issues through YouTrack or the support request form. If you‚Äôd like to stay informed about accessibility improvements, you can subscribe to updates here.

21.05.2026 10:40:41

Investigativní

Komentáře

Kryptoměny a Ekonomika

Sport

Svět

Technologie a věda

Technologie a věda
4 dny

Patients who use mobile applications to manage medical conditions including depression and chronic pain might assume the apps have been evaluated by regulatory agencies to be safe and effective. But that isn’t necessarily the case.Most of the more than 55,000 medical apps that claim to diagnose or treat a condition—or ones that provide clinical decision support, known as “therapeutic” apps—have never been assessed by any trusted neutral bodies or regulatory agencies to evaluate them for technical soundness, ethical design, or clinical benefit. The apps often don’t comply with regional data security and privacy laws to protect people’s sensitive health information.Medical apps differ from traditional wellness apps, which provide users with insights into becoming healthier by, for example, tracking fitness activities, monitoring blood pressure, and analyzing sleep patterns.There is no reliable way to verify that therapeutic apps deliver the results they indicate. To help ensure such apps are credible, the IEEE Standards Association (IEEE SA) recently launched the IEEE Global Medical Mobile App Assessment and Registry. The publicly searchable directory is designed to list apps that have been vetted by experts across several criteria including technical soundness, ethical design, compliance with data security and privacy regulations, and clinical efficacy, which is evidence of a clinical benefit for the patient.“Patients, clinicians, payers, and health care systems often struggle to distinguish clinically meaningful therapeutic apps from those that are simply well-marketed,” says IEEE Senior Member Yuri Quintana, chair of the assessment and registry program. He is chief of the clinical informatics division at Beth Israel Deaconess Medical Center, in Boston. “Our goal is to establish a standardized review method using criteria developed by experts.”Why regulation is lackingBecause the apps are intended for medical use without being part of a medical implement, they fall under the designation of software as a medical device (SaMD), according to the International Medical Device Regulators Forum. SaMD is supposed to be regulated by public health agencies such as the U.S. Food and Drug Administration, but the apps have developed and grown in popularity so quickly that regulators haven’t been able to keep up, Quintana says. Some companies have received approval, but most have not, he says.Many users are unaware of the regulatory gap, he says.“Seeing an app from a well-known company often creates the impression that it has been meaningfully vetted for safety and efficacy, even when that is not the case,” he says.Some companies are using deceptive advertising to sell their product, he adds. Marketing materials might claim that all of a company’s health apps are certified, even though only one app has been approved by a regulatory body to treat a particular condition. Or the verbiage might imply the company has clinical evidence proving its application works, even though the app has never been tested independently.Another concern is that updated apps aren’t being vetted, says Maria Palombini, IEEE SA’s director of health care and life sciences global practice lead.“The original app might have received approval from a regulatory agency, but not the updated version,” Palombini says. “There could have been significant changes from the original.”“Not every medical-related app triggers the same regulatory classification or review across jurisdictions,” Quintana adds. “That leaves a large gray zone of clinically relevant but lower-risk apps that haven’t undergone an independent assessment. The IEEE registry was created to help fill these gaps.“IEEE is the best organization to address this problem because this is fundamentally a standards, trust, interoperability, and conformity assessment challenge,” he says. IEEE “is the world’s largest technical professional organization, with deep expertise in developing globally recognized standards including in health care, cybersecurity, AI ethics, and interoperability.”“Through the IEEE Conformity Assessment Program, we already run rigorous assessment and registry programs,” Palombini says. “Our neutral, consensus-driven, multidisciplinary approach—bringing together clinicians, regulators, developers, and ethicists without commercial bias—makes IEEE uniquely positioned to create trustworthy global guardrails that can scale across jurisdictions and support regulatory harmonization.”How the registry worksThe assessment framework was developed by a multidisciplinary group of 35 volunteer experts from 10 countries, Quintana says. The panel includes academics, AI experts, app developers, clinicians, ethicists, mental health experts, patient advocates, regulators, researchers, technologists, and those who assess safety in health care.The registry is for any app used for clinical care or therapeutics that claims to demonstrate a medical benefit. That includes apps designed for cardiology, diabetes, mental health, neurology, oncology, rehabilitation, and respiratory diseases, Quintana says.Initially, he says, the focus will be on apps that aim to treat mental health conditions, given the large number of offerings in that area and the registry committee’s expertise.The submission of apps is voluntary. There is no government mandate that requires a company to use the IEEE registry.The products will be evaluated against about 150 consensus-based criteria across three major areas: Clinical efficacy including therapeutic effectiveness, any sustained benefits, risk management, comparison to standard care, user engagement, and real clinical value.Technical soundness including accessibility, privacy and security, error handling, interoperability, AI governance, usability, and operational quality.Ethical design including bias prevention, patient consent, data governance, conflict-of-interest transparency, responsible use of AI and large language models, and prioritization of public health benefits.IEEE charges a nonrefundable submission fee that covers the cost of the assessment plus the registry’s annual subscription for the first year.Developers first must demonstrate they are a legally established entity before they can complete the app publisher registration form and then submit documentation and attestations about the product.The IEEE review of an app is estimated to take six to eight weeks, Palombini says. The assessment results will be privately shared with the app publisher, she says, and to be listed in the registry, an app must achieve more than 85 percent compliance in each category.Upgraded apps must be submitted and reassessed, Palombini says. Similar to how users are notified when an app on their smart devices has , the registry will be notified when listed apps have a new update available, she says.Applicants who do not pass the assessment are to receive feedback explaining why. They will be given an opportunity to make changes or provide additional documentation, Palombini says.“It’s a pretty methodological process, with checks and balances,” Quintana says. “We’re being very transparent about the process.”Approved apps added to the registry receive an IEEE certification badge and submission identifier, which the company can display on its website, app store listings, and marketing materials.“The badge serves as visible proof that the app has met the independent, consensus-based assessment for clinical value, technical robustness, and ethical design,” Quintana says.The registry will be publicly available at no cost, he says.Patients and families seeking safe, trustworthy apps—and payers and insurers evaluating reimbursement potential—will find the registry helpful, he says.The application website is open. The public registry page does not yet list a specific count of approved apps because assessments are ongoing. Approved apps and their unique identifiers are to be published when the initial reviews are completed.To learn more, you can watch a webinar recorded in March.The assessment framework that underpins the registry is supporting the formal recognition of IEEE P3962 Standard for Criteria Assessment Framework f

21.05.2026 18:00:01

Technologie a věda
4 dny

Discover how the ZEISS Crossbeam 750 FIBSEM sets a new benchmark for precise TEM lamella prep, tomography, and advanced nanofabrication. This delivers better resolution, better SNR, larger usable FOV, and shorter acquisition times. Learn how uninterrupted FIB milling will reduce damage and rework, accelerate time to TEM, and increase first pass success—so your FA, yield, and materials teams make faster, confident data driven decisions.Join us to discover how the new ZEISS Crossbeam 750 with its see while you mill capability delivers precision and clarity—every time—for demanding FIB-SEM workflows. Designed for extremely challenging TEM lamella preparation, tomography, advanced nanofabrication, and APT‑ready lift‑out, Crossbeam 750 combines a new Gemini 4 SEM objective lens, a double deflector, and a next‑generation scan generator to elevate both image quality and process confidence. You’ll learn how better resolution and better SNR translate into more image detail and shorter acquisition times, while the low‑kV FIB performance enables more precise lamella prep.We’ll demonstrate High Dynamic Range (HDR) Mill + SEM—an interwoven SEM/FIB scanning mode that suppresses FIB‑generated background. This enables immediate, clean visual feedback, even during nudging the FIB pattern live while milling . The result: confident endpointing with uninterrupted FIB milling and pristine, metrology‑grade surfaces with the lowest possible sample damage. This session is ideal for semiconductor failure analysists, yield teams and materials scientists seeking faster time‑to‑TEM, higher first‑pass success, and consistent outcomes at low kV. See how Crossbeam 750 empowers you to make earlier stop‑milling decisions, cut rework, and reliably plan turnaround time—so you can move from sample to insight with confidence.Register now for this free webinar!

21.05.2026 10:00:02

Technologie a věda
4 dny

This sponsored article is brought to you by Wetour Robotics.A field technician on a wind turbine, harness clipped, both hands on a wrench, needs to send a command to the diagnostic device hanging at her belt. A logistics worker on a loading dock, gloves on, eyes on the pallet, needs to redirect a connected lift. A person using an assistive mobility device on a crowded street wants to nudge it forward without taking out a phone or speaking aloud. None of these moments call for a smarter robot. They call for a smarter way to be heard by the machines that already exist.The industry has been building from one sideThe past three years of Physical AI have been a story of remarkable progress on the robot side of the loop. Companies like Boston Dynamics, Figure, and Unitree have advanced actuators, locomotion, and dexterity to a level that would have seemed implausible a decade ago. Google DeepMind’s Gemini Robotics has redefined what vision-language-action models can do in unstructured settings. The trajectory of the hardware and the foundation models is real, and it is accelerating.But there is another side to this loop, and it has been treated as a solved problem for too long. The interface between humans and machines has defaulted, for 40 years, to three input modalities: screens, buttons, and voice. Each of those assumes the user can stop, look down, and translate intent into structured commands. That assumption breaks the moment the work moves into a real environment. On a turbine. On a dock. On a sidewalk. In any setting where hands are occupied, eyes are committed, or speaking is impractical, the conventional interface stack quietly fails.Spatial Intent Fusion is the simultaneous processing of three streams of human-centered information, namely spatial position, visual context, and gestural intent: Your body is the interface.The bottleneck on the human side of the loop is becoming as important as the one on the machine side. And solving it requires a different question. Not how do we make the robot more capable, but how do we let the human participate in the computing system as naturally as the robot already does.Wetour Robotics’ bet: put the human back into the computing loopWetour Robotics is betting that the next architectural leap in Physical AI is not about making the robot more capable. It is about making the human a first-class node in the computing network, with the same kind of low-latency, high-fidelity participation that connected devices already enjoy.Wetour Robotics’ engineers frame the problem this way: a wristband that recognizes a gesture is not enough. A camera that recognizes a scene is not enough. The information a human carries about what they are about to do is distributed across multiple channels, including where their body is in space, what their eyes are attending to, and what their muscles are preparing to do, and any single channel observed in isolation is ambiguous. Reconstructing intent reliably means fusing those channels at the operating system level, with latency low enough that the loop feels closed rather than mediated.This approach has a name. Wetour Robotics calls it Spatial Intent Fusion: the simultaneous processing of three streams of human-centered information, namely spatial position, visual context, and gestural intent, fused into a single real-time command for any connected physical device. It is the technical implementation behind a simpler positioning statement the company uses externally: your body is the interface. Orchestra is a portable intelligent hub running the operating system that handles sensor fusion, intent inference, command translation, and safety arbitration. The reference compute platform is NVIDIA Jetson Orin Nano Super, which provides enough on-device inference capacity to keep the entire control loop at the edge, with no cloud dependency on the critical path. Wetour RoboticsThe architecture: three layers, four engines, one loopOrchestra is not a single device but a layered platform, designed from the start to be sensor-flexible and actuator-agnostic. The architecture decomposes into three perception layers and four coordination engines.Orchestra itself is the local compute and orchestration core: a portable intelligent hub running the operating system that handles sensor fusion, intent inference, command translation, and safety arbitration. The reference compute platform is NVIDIA Jetson Orin Nano Super, which provides enough on-device inference capacity to keep the entire control loop at the edge, with no cloud dependency on the critical path. Edge inference is non-negotiable for this application. Full-chain latency from biosignal acquisition to actuator command is held under 100 milliseconds, the envelope inside which closed-loop control feels natural rather than laggy.VisionLink handles visual and spatial perception. Cameras feed into vision models that identify objects, estimate distances, and track environmental context. VisionLink is designed not as a passive recognition layer but as a real-time command generator: its outputs feed directly into Orchestra OS to be fused with biosignal data.Conductor is the biosignal pipeline. It ingests raw surface electromyographic (sEMG) data from a wrist-worn device, classifies temporal patterns into discrete gestures or continuous control signals, and outputs actuator commands. The technically interesting property of sEMG for this use case is that the signal precedes visible motion. Motor unit action potentials appear at the skin surface roughly 50 to 80 milliseconds before a finger completes the corresponding gesture. Wetour Robotics calls this property pre-motion intent sensing, and it is what allows Orchestra to anticipate user intent rather than react to it.On top of the three perception layers, Orchestra OS runs four coordination engines. The Perception Engine ingests and normalizes raw sensor streams. The Intent Engine performs Spatial Intent Fusion across modalities, resolving what the user is trying to do given where they are, what they are looking at, and what their hand is signaling. The Orchestration Engine translates intent into device-specific command sequences for any connected actuator. The Safety Engine arbitrates conflicting commands, enforces operational envelopes, and gates execution against runtime safety conditions. Wetour RoboticsThe trade-offs we’re honest aboutNo system that bridges the human body and the digital world is finished. Three engineering challenges remain open, and the company addresses each with a deliberate trade-off rather than a claim of having fully solved it.Baseline stability of sEMG under motion. In a stationary user, continuous gesture recognition from sEMG is reliable. Once the user is walking, climbing, or otherwise moving, motion artifacts and electrode drift degrade the signal in ways that are difficult to fully compensate for. Rather than overpromise on continuous control in dynamic settings, Orchestra defaults to a smaller set of robust discrete gestures in complex operating environments, and reserves continuous control modes for contexts where the signal-to-noise ratio supports them.Miniaturization of edge AI compute. Running the Orchestra control loop entirely at the edge requires real on-device inference, which has historically meant trading off between compute capacity, battery life, and form factor. Wetour Robotics’ approach has been a compact carrier board paired with a thermal design and a battery module sized for all-day wearability. The result is a hub that travels with the user rather than tethering them to a desk, and that performs the full perception-to-actuation loop without offloading to the cloud.Heterogeneity of third-party device protocols. The actuator side of the loop is a fragmented landscape. Different manufacturers expose different command interfaces, different communication stacks, and different safety conventions, and a Physical AI operating system has to integrate with all of them. Wetour Robotics uses an AI-agent layer to negotiate connection and protocol translation adaptively, so that Orchestra OS can ingest data from a wide range of devices, run them through neural network models that infer human intent, and emit the right command on the right protocol for the device on the other end.Why this matters, and why it helps the rest of the fieldThe history of computing is a history of interface revolutions. Command lines gave way to graphical user interfaces, which gave way to touch, which gave way to voice. Each transition expanded who could participate in the system and what they could do with it. The next transition is not about a new screen or a new microphone. It is about treating the human body itself as a participant in the computing network, capable of contributing intent at the same speed and fidelity that any other connected node can.The history of computing is a history of interface revolutions. The next transition is not about a new screen or a new microphone — it is about treating the human body itself as a participant in the computing network.This path is not a competitor to the work being done on humanoid robots, foundation models for embodied AI, and dexterous manipulation. It is the missing complement to that work. The hardest open problem for humanoid systems is the data: every natural interaction between a human and the physical world is a potential training signal, and most of those interactions are currently invisible to any computing system. As more humans become first-class nodes in the loop, those interactions become observable, structured, and ultimately useful for training the next generation of embodied AI, including the humanoid robots being developed today.In other words: putting the human back into the computing loop is not just about better interfaces for individual users. It is about generating the kind of grounded, in-the-wild human-machine interaction data that the broader Physical AI ecosystem will need to keep advancing. The robot side and the human side of the loop are not two competing futures. They are two halves of the same one.That is what Wetour Robotics means when it says: Your body is the interface.Learn more at wetourrobotics.com.

21.05.2026 10:00:02

Technologie a věda
5 dní

Over the next few decades, billions of autonomous, AI-powered robots will work alongside people in factories, perform tedious tasks in warehouses, care for the elderly, assist in unsafe disaster areas, deliver packages and food to our doorsteps, and eventually help out in our homes. Some will look like us, and many won’t. What is certain is that regardless of form factor, robots will all rely heavily on AI in order to deliver real-world value.In 2025, total investments in robotics companies reached a record US $40.7 billion, accounting for 9 percent of all venture funding. The multibillion dollar question therefore is this: What will it take for AI-powered robots to begin to have a serious economic impact? Many of today’s robotics and AI companies are making bold claims, such as that humanoid robots will soon be coming into our homes, but there’s still a big gap between promise and reality.The promise of robots that live and work alongside us has been the stuff of science fiction for a very long time. And while many programmers have tried to make that promise a reality, the physical world is just too complicated for traditional computer programs to handle the endless complexity it presents. Thanks to AI, robots are no longer being programmed—instead, they learn to operate in the real world. With enough practice, they can learn to perceive and understand the world around them, reason about that world, and use that reason and understanding to perform tasks that are useful, reliable, and safe.The two of us have worked at the forefront of AI and robotics for the last decade, as a Professor in Robotics at Oregon State University and Co-Founder of Agility Robotics, and as former CEO of the Everyday Robots moonshot at Google X. Our experience deploying AI-powered robots in real-world settings has given us a perspective on where AI can be used to great benefit in complex robotic systems in the near term and where we are still on the frontier of science fiction. We believe AI will enable an inflection point in robotics advances, but that it will be through the well-engineered application of coordinated systems of different AI tools rather than a single ChatGPT-style breakthrough.As the excitement around AI is matched only by the uncertainty of what will be possible, here are five hard truths that will define AI in robotics.1. The YouTube-to-Reality Gap Is RealFor years, we have been seeing videos on YouTube with humanoid robots performing amazing moves on everything from a dance floor to an obstacle course. The inside knowledge in robotics is to “never trust a YouTube robot video.” The gap between real robots that can perform real work in unstructured human environments and carefully scripted and edited robot performances remains significant. The latest performance to get a lot of attention was a martial arts show featuring Unitree humanoid robots performing with children at the Chinese 2026 Spring Festival Gala. While impressive, this falls into a long lineage of tightly scripted robotic performances, where everything has been carefully choreographed and planned in advance. The low-level controls, synchronization, and choreography were stunning, yet the Spring Gala robot performance showed a level of autonomy and intelligence much closer to industrial robots building cars in a factory than something that will show up in your living room any time soon. Seeing these kinds of demos nevertheless raises questions about where robotics really is. If robots can perform kung fu moves and do backflips and dance, why aren’t they also showing up on factory floors yet? And why can’t they do the dishes in my home after dinner? The simple answer is this: Making AI-powered robots capable of performing general tasks in varied human environments is still really hard. While impressive technological feats like those at the Spring Festival may make it look like we could be very close, the use of AI in these demos is only for low-level motor control (to keep the robots from falling over) and therefore is only a small part of the solution for robots to be general purpose in the real, unstructured spaces where we humans live and work.2. Data Is An Unsolved ChallengeLarge Language Models (LLMs) like OpenAI’s ChatGPT and Anthropic’s Claude were initially trained on an internet-scale database of text. The world woke up one day in late 2022 to ChatGPT demonstrating that AI computers could suddenly “speak” to us in prose or verse and about seemingly any topic. LLMs have turned out to generalize well and are now able to take multimodal input (text, images, video) and produce multimodal output. Importantly, the corpus of training data was both enormous and human-generated, which are characteristics that form the gold standard for AI training. The fastest path to robots as part of everyday life may emerge through a range of robot forms performing increasingly sophisticated applications and employing a range of AI tools.Agility RoboticsGiving AI a body (in the form of a robot), so that it can engage with people in the physical world, continues to be a very difficult and broadly unsolved problem. AI models for general-purpose robotics must simultaneously satisfy multiple, often conflicting, physical, geometric, and temporal limitations while operating in unstructured, dynamic environments. In order to generalize, robot models need to be trained on data gathered in a high-dimensional configuration space, where “dimensions” represent text, lighting conditions, degrees of freedom, joint limits, velocities, force, and safety boundaries, just to mention a few. Importantly, this must be good data—it must contain many examples from what amounts to an infinite number of possible configurations in the physical world.Since there are very few existing sources of data like this, approaches like teleoperation, video analysis, motion capture of humans, and self-exploration in simulation and in the real world are all seen as important ways to collect data. It’s a herculean task. For example, at Everyday Robots at Google X, we ran 240 million robot instances in our simulator over the course of 2022 to collect training data, mostly to train a trash-sorting model. Similar amounts of data will be needed for every skill to get to a similar level of capability, which is not yet human level.3. There Will Be No Single Robot AIWe are far away from a moment where a single AI model might allow general-purpose robots to live and work alongside us. General-purpose robots can have wheels or legs. They can have one, two, three, or more arms. Some have propellers and can fly, while others may be designed to operate under water. Some will drive on busy roads. The physical world is infinitely varied and complex. And then there are all the people and other animals that will be surrounding the robots. How do you train a model to operate a robot safely and reliably in all of these settings? The simple answer is: You don’t. At least not for quite some time.We believe the winning AI architecture leading to the next big breakthroughs in general-purpose robotics will be “agentic AI” for robots, which are high-level coordinating models that can reason, plan, use tools, and learn from outcomes to execute complex tasks with limited supervision. Agentic, high-level models running on robots will invoke a system of specialized ones for different types of tasks. We will likely soon see multiple robots collaborating and coordinating with each other through their onboard agentic AI models.AI tools are unlocking new and powerful capabilities in robotics, which in turn will enable new solutions and new markets. It’s encouraging to see these new models being made broadly available, some even as open-source solutions. This availability is akin to what happened with the internet: Real progress occurred when it became ubiquitous. We anticipate an inevitable democratization of complex behaviors in robotics with wide access to these AI tools and technologies.4. Hardware Is Still Very HardRobots are complex systems with many parts that all need to work together with great precision. For a robot to be useful and safe, every part of it must be coordinated, from its perception systems to the computer controlling it, all the way down to its individual actuators.Actuators—that is, the motors and gears—are a good example of an important part of the robot where what got us here won’t get us there. The actuators used at scale by most industrial robots will not work for robots that will operate in human environments. If these robots accidentally collide with an obstacle, the resulting impacts are harsh, forces are high, and things break. Humans don’t move in this way. We are far more compliant in how we interact with the world, and we’re constantly making contact with our environment and using that contact to help us accomplish things. Consider the challenge of inserting a key in a lock: Humans typically don’t do this by aligning the key perfectly with the keyhole. Instead, we just feel for the edge of the keyhole and jiggle the key in. Robots need to be able to operate in novel ways to achieve comparable capabilities by using a new class of actuators that are sensitive to force and able to have a compliant interaction with the environment. While these kinds of actuators do exist, they are not yet generally available at scale for robot systems designed to operate around people.5. Real Value Comes From “Easy” TasksThere’s a big difference between tasks that look impressive and real-world tasks that provide value. Robotics is a perfect example of Moravec’s paradox, which states that tasks that are hard for humans are easy for computers (like multiplying two big numbers), and tasks easy for humans (like a toddler’s movements) are extremely difficult for computers and robots.Serving customers is an unforgiving reality check, because customers only care about solving the real problems they have. If we are to deploy AI-based robot solutions, they must outperform the way things are currently done while demonstrating reliable performance metrics and safety. Agility Robotics’ early work to deploy our humanoid robot Digit in customer locations led to the realization that our first obstacle was safety: Robots that balance and manipulate objects in human spaces bring new types of risk to the workplace. In the first humanoid deployments, physical barriers were necessary, and Agility kicked off a multi-year engineering effort to solve the safety challenge, touching nearly every aspect of robot design and relying heavily on new AI-based approaches to human detection and behavior control. Everyday Robots at Google deployed robots in 2019 that worked autonomously in office buildings doing chores like cleaning cafe tables and sorting trash. We quickly learned how “messy” and difficult the real world is for a robot. This experience informed the architecture and deployment of our AI systems while also gathering real-world data that could be combined with simulation data for training and improving models.This focus on creating a product to meet specific customer needs and deploying robots in real-world settings is the only way to inform the structure of the AI tools and infrastructure for near-term utility on a path towards long-term broader capability and generality. There will be no “aha” moment, no silver bullet algorithm, and no volume of data sufficient to produce a general-purpose robot without extensive real-world experience. AI Robots Are Coming, One Step at a TimeAs we look to the future, there is no doubt that the world is bringing AI into the physical world through robots. We are at the beginning of a “Cambrian explosion“ of useful, intelligent machines. We believe AI is not one tool, but a huge frontier of technical approaches that is unlocking new capabilities so powerful, they will define our economy moving forward. This will happen not in one single definitive moment, but as an ongoing set of small and large breakthroughs, where AI-driven robots begin to provide real value in a few tasks, and then a few more, with impacts unfolding across numerous $100 billion-plus markets that will dramatically improve the quality of our lives.

20.05.2026 11:00:01

Technologie a věda
7 dní

In the late 1940s—when computer engineers were grappling with unreliable hardware and noisy transmission environments—a team of engineers inside a modest lab at the University of Manchester, England, confronted a problem so fundamental that it threatened the viability of digital computing itself. Machines could generate bits, but they could not reliably read them back.The inconsistent reading back of memory data did not initially present itself as a grand theoretical challenge. It showed up as something more mundane: inconsistent computing results.Engineers including Frederic C. Williams, Tom Kilburn, and G. E. (Tommy) Thomas traced the failures not to logic errors but to the physical behavior of the machines themselves. The team devised a technique for keeping a transmitter and a receiver synchronized without relying on a separate clock signal. Their innovation, known as Manchester code or phase encoding, encoded each bit with a transition in the middle of the bit period, effectively embedding timing information directly into the data stream to be a self-clocking signal. So, even if the signal degraded or the timing drifted slightly, the receiver could continually keep time based on those regular transitions.By eliminating the need for separate clocks and reducing synchronization errors, Manchester code made data transfer more robust across cables and circuits.Those qualities later made it a natural fit for technologies such as Ethernet and early data storage systems. Its self-clocking nature helped standardize how machines communicate, and it laid the groundwork for modern networking and digital communication protocols.On 13 April 2026, this breakthrough was honored with an IEEE Milestone plaque during a ceremony at the University of Manchester. Dignitaries from IEEE and the university attended the ceremony.Embedding timing in signalsThose 1940s Manchester University engineers were working on systems that fed into the Manchester Mark I, one of the first practical stored-program machines.When troubles arose, they used oscilloscopes to probe signals. They found that electrical pulses did not arrive with consistent timing. Memory signals also blurred over time, making them harder to read, and when long runs of identical bits occurred, the waveform flattened into stretches with no transitions.That led to a crucial insight: The problem was not just detecting whether a signal was high or low; the system also lost track of when to sample the signal. Without reliable timing markers, even correctly formed signals were misread. Bits could effectively be lost or miscounted because the system fell out of sync.At first, the engineers tried to tame the hardware. They experimented with stabilizing circuits and more consistent pulse generation, attempting to impose a regular rhythm on an inherently unstable system. But the fixes proved fragile, and the electronics of the day could not maintain the required precision. So the Manchester group took a different approach.If the hardware could not provide a dependable clock, the signal itself would have to carry one. Instead of representing data as static levels, each bit changed state, with a guaranteed transition in the middle.Embedding timing in the signal reduced erratic behavior. Machines were suddenly able to reliably transmit, store, and read back data—an essential step toward practical stored-program computing.Making signals unmistakableThe Manchester code addressed several issues at once. Regular transitions allowed continuous timing recovery. Transitions proved easier to detect than static levels, and long runs of identical bits no longer produced flat, ambiguous waveforms. Rather than fighting the imperfections of early electronics, the design worked with them.From lab curiosity to a global standardWhat began as a local solution in Manchester shaped digital communication systems for decades, including early Ethernet technology, for which timing and shared-medium communication were central challenges.According to Robert Metcalfe, a member of the team that built the first Ethernet system at Xerox PARC in 1973, he and his colleagues relied on Manchester code.“Manchester code solved a fundamental problem for us: timing,” Metcalfe says, explaining that each bit carried its own clock and removed the need for a global synchronized signal.That self-clocking property wasn’t the only benefit provided by the encoding scheme. On a shared coaxial cable, Manchester encoding did more than provide timing. Each transceiver left the medium undriven—effectively “off”—most of the time, allowing packets from other machines to pass without interference. Even during transmission, a station drove the signal only about half the time, leaving the line undriven during the other half of each bit cycle.This distinction—between a driven signal and an undriven line, rather than simple 1s and 0s—allowed receivers to recover both data and clock timing while also monitoring the cable for other activity. If a transceiver detected a signal when it expected the line to be undriven, the signal indicated that another station was transmitting at the same time. In other words, the system could detect collisions in real time and respond accordingly.The idea has proven durable far beyond local networks. Manchester code is being used aboard the Voyager spacecraft, which are now cruising through interstellar space—underscoring its reliability in extreme environments.The code also has found its way into everyday consumer electronics. Infrared remote controls for televisions and audio equipment commonly rely on Manchester code through protocols such as RC-5, developed by Philips in the early 1980s. The protocol encodes commands as timed infrared signals transmitted by a handset’s integrated circuit and LED, allowing devices to reliably interpret button presses even through noise and signal distortion. Manufacturers across Europe—and many in the United States—adopted the approach, extending Manchester code into the home.Why the Milestone mattersAn IEEE Milestone designation recognizes technologies with enduring impact. Manchester code qualifies because it solved a foundational timing problem at a critical moment in computing history.Without a way to embed timing in the data itself, early digital systems would have remained fragile and unreliable. Manchester code helped transform them into dependable machines, and it enabled much of today’s digital communication.“Manchester code solved a fundamental problem for us: timing,” —Robert Metcalfe, an Ethernet inventorKey participants at the plaque dedication ceremony included Tom Coughlin, 2024 IEEE president; Duncan Ivison, University of Manchester president and vice chancellor, and Nagham Saeed, chair of the IEEE U.K. and Ireland Section.Talks by Kees Schouhamer Immink (the 2017 IEEE Medal of Honor laureate probably best known for his work that made compact discs and other high-density digital media practical) and Peter Green (Manchester’s deputy dean for the engineering faculty) highlighted the code’s lasting impact on digital data storage and communications.The IEEE Milestone plaque for the Manchester code reads:“At this site in 1948–1949, Manchester code was invented for reliably encoding digital data stored on the Manchester Mark I computer’s magnetic drum. It became a standard for computer magnetic tapes and floppy disks and was used in digital communications, including the Voyager 1 and 2 spacecraft and early Ethernet networks. It found wide use in domestic remote controllers, radio frequency identification (RFID) tags, and many control network standards.”Administered by the IEEE History Center and supported by donors, the Milestone program recognizes outstanding technical developments worldwide. The IEEE U.K. and Ireland Section sponsored the nomination.

18.05.2026 18:00:01

Technologie a věda
7 dní

For years, the field of robotics has used the terms “dull, dirty, and dangerous” (DDD) to describe the types of tasks or jobs where robots might be useful—by doing work that’s undesirable for people. A classic example of a DDD job is one of “repetitive physical labor on a steaming hot factory floor involving heavy machinery that threatens life and limb.”But determining which human activities fit into these categories is not as straightforward as it seems. What exactly is a “dull” task, and who makes that assumption? Is “dirty” work just about needing to wash your hands afterwards, or is there also an aspect of social stigma? What data can we rely on to classify jobs as “dangerous?” Our recent work (which was not dull at all) tackles these questions and proposes a framework to help roboticists understand the job context for our technology.First, we did an empirical analysis of robotics publications between 1980 and 2024 that mention DDD and found that only 2.7 percent define DDD and only 8.7 percent provide examples of tasks or jobs. The definitions vary, and many of the examples aren’t particularly specific (for example, “industrial manufacturing,” “home care”). Next, we reviewed the social science literature in anthropology, economics, political science, psychology, and sociology to develop better definitions for “dull,” “dirty,” and “dangerous” work. Again, while it might seem intuitive which tasks to put into these buckets, it turns out that there are some underlying social, economic, and cultural factors that matter.Dangerous Work: Occupations or tasks that result in injury or risk of harmIt’s possible to measure the danger of a task or job by using reported information. There are administrative records and surveys that provide numbers on occupational injury rates and hazardous risk factors. While that seems straightforward, it’s important to understand how this data was collected, reported, and verified.First, occupational injuries tend to be underreported, with some studies estimating up to 70 percent of cases missing in administrative databases. Second, injuries and risk factors are rarely disaggregated by characteristics like gender, migration status, formal/informal employment, and work activities. For example, because most personal protective equipment—such as masks, vests, and gloves—are sized for men, women in dangerous work environments face increased safety risks.These caveats are an opportunity for robotics to be helpful. If we went out and looked for it, we could probably find some less obviously dangerous work where robotics might be an important intervention, not to mention some groups that are disproportionately affected and would benefit from more workplace safety.Dirty Work: Occupations or tasks that are physically, socially, or morally taintedColloquially, most people might think of dirty work as involving physical dirtiness, such as trash removal, cleaning, or dealing with hazardous substances. But social science literature makes clear that dirty work is also about stigma. Socially tainted jobs are often servile or involve interacting with stigmatized groups (for example, correctional officers), and morally tainted jobs include tasks that people commonly perceive as sinful, deceptive, or otherwise defying norms of civility (like a stripper or a collection agent).“Dirty work” is a social construct that can vary across time (like tattoo industry stigma in the United States) and culture (such as nursing in the U.S. versus in Bangladesh). One way to measure whether work is “dirty” is by using the closely related concept of occupational prestige, captured through quantitative surveys where people rank jobs. Another way to measure it is through qualitative data, like ethnographies and interviews. Similar to “dangerous,” we see some hidden opportunities for robotics in “dirty” work. But one of our more interesting takeaways from the data is that a lower-ranked job can be something that the workers themselves enjoy or find immense pride and meaning in. If we care about what tasks are truly undesirable, understanding this worker perspective is important.Dull Work: Occupations or tasks that are repetitive and lacking in autonomyWhen it comes to defining dull work, what matters most is workers’ own experiences. Outsiders can make a lot of false assumptions about what tasks have value and meaning. Sometimes things that seem boring or routine create the right conditions for developing skills and competence, such as the concentration needed for woodworking, or for socializing and support, when tasks are done alongside others. Instead of assuming that repetitive work is negative, it’s important to examine qualitative data on how people experience the work and what purpose it serves for them.DDD: An actionable frameworkIn our paper, we propose a framework to help the robotics community explore how automation impacts individual jobs. For each term—dull, dirty, and dangerous—the framework gathers key pieces of information to reflect on what physical or social aspects of the task are, in fact, DDD. Worker perspective is an important part of all three considerations. The framework also emphasizes awareness of context—meaning the physical and social environment of an occupation and industry that can influence the DDD nature of a task. Our corresponding worksheet suggests existing data sources to draw on and encourages us to seek out multiple perspectives and consider potential sources of bias in the information. What makes tasks dull, dirty, or dangerous depends on the perspective of the humans doing those tasks.RAILet’s take, for example, the waste and recycling industry. The world generates over 2 billion tonnes of waste annually, and this figure is expected to rise to nearly 4 billion tonnes by 2050. Intuitively, trash collection seems like a job that hits all the Ds. Going through our worksheet, we confirm that globally, workers in this industry face significant health hazards (dangerous), and waste collection is ranked as a low-status job (dirty), although interestingly, many workers take pride in providing this essential service.The job is also repetitive, but there are aspects that make it not dull. Specifically, workers cite the day-to-day interaction with their coworkers (which includes extensive insider vocabulary, work hacks, and mutual aid groups) and task variety as two of the most enjoyable aspects of the job. Task variety includes inspecting their vehicle and equipment, driving their truck, coordinating with crew members, lifting bins and bags, detecting incorrect sorting of waste, and unloading at the end destination.This finding matters because some types of robotic solutions will eliminate the parts of the job that workers most appreciate. For instance, the National Institute for Occupational Safety and Health (NIOSH) recommends the adoption of automated side loader trucks and collision avoidance systems. This innovation increases safety, which is great, but it also results in a sole worker operating a joystick in a cab, surrounded by sensor and camera surveillance.Instead, we should challenge ourselves to think of solutions that make jobs safer without making them terrible in a different way. To do this, we need to understand all aspects of what makes a job dull, dirty, or dangerous (or not). Our framework aims to facilitate this understanding.Finally, it’s important to note that DDD is only one of many possible approaches to classify what work might be better served by robots. There are lots of ways we could think about which types of tasks or jobs to automate (for example, economic impact or environmental sustainability). Given the popularity of DDD in robotics, we chose this common phrase as a starting point. We would love to see more work in this space, whether it’s data collection on DDD itself or the creation of other frameworks.At RAI, we believe that the fusion of robotics and social sciences opens a whole new world of information, perspectives, opportunities, and value. It fosters a culture of curiosity and mutual learning, and allows us to create actionable tools for anyone in robotics who cares about societal impact.Dull, Dirty, Dangerous: Understanding the Past, Present, and Future of a Key Motivation for Robotics, by Nozomi Nakajima, Pedro Reynolds-Cuéllar, Caitrin Lynch, and Kate Darling from the RAI Institute, was presented at the 21st ACM/IEEE International Conference on Human-Robot Interaction (HRI) in Edinburgh, Scotland.

18.05.2026 13:00:00

Technologie a věda
7 dní

This sponsored article is brought to you by Melbourne Convention Bureau (MCB) supported by Business Events Australia.Melbourne’s reputation as a global events city, from the Australian Open tennis and Formula 1 Australian Grand Prix to hosting NFL regular season games, now intersects with a different form of scale: large-scale compute, data-intensive research, and advanced engineering. Long recognized for delivering complex international events, the city is applying the same organisational capability to the infrastructure that underpins modern AI research, positioning Melbourne at the convergence of global convening and high-performance digital systems.Consistently ranked among the world’s most livable cities, Melbourne was named Time Out’s Best City in the World in 2026, the first Australian city to hold the title. Melbourne, Australia’s premier conference destination. Tourism Australia More materially for research and innovation, Melbourne is also the nation’s fastest‑growing capital, attracting increasing concentrations of engineering and technology talent, investment and international engagement.Australia’s artificial intelligence (AI) ecosystem is entering a new phase, defined less by isolated initiatives and more by the convergence of compute infrastructure, research intensity and international collaboration. Melbourne sits at this intersection.Melbourne’s trajectory highlights what enables research at scale: access to frontier-grade compute, proximity to industry-ready infrastructure, and repeated opportunities for global research communities to convene.Sovereign AI compute, expanding hyperscale data center campuses and a growing pipeline of international research-led conferences are reshaping the city’s research landscape. Together, these elements position Melbourne as a focal point for applied AI research, advanced engineering and data-intensive science.The growing global influence of AI engineering, underscored by NVIDIA CEO Jensen Huang receiving the 2026 IEEE Medal of Honor, reflects the scale of this shift. In Melbourne, these factors form a reinforcing research flywheel linking infrastructure, discovery and collaboration.Rather than focusing on startup density or short-term commercial output, Melbourne’s trajectory highlights what enables research at scale: access to frontier-grade compute, proximity to industry-ready infrastructure, and repeated opportunities for global research communities to convene. NVIDIA CEO Jensen Huang received the 2026 IEEE Medal of Honor.IEEESovereign AI foundationsThe most recent cornerstone of Melbourne’s AI capability is MAVERIC (Monash AdVanced Environment for Research and Intelligent Computing), Australia’s largest university-based AI supercomputer. Built and deployed by Monash University in partnership with NVIDIA, Dell Technologies, and CDC Data Centres, MAVERIC has been engineered specifically for large scale AI and data intensive science, with medical research representing a key priority. Indeed, in these regards MAVERIC has been designed to function as a Next Generation Trusted Research Environment thus ensuring that it is state-of-the-art and provides a safe and secure framework for the analysis of large sensitive datasets.Designed to support research projects including cancer and neurodegenerative disease detection, clinical trial analysis and drug discovery through to materials science and engineering, MAVERIC enables Australian researchers to train and evaluate large models domestically while keeping highly sensitive datasets secure and under national jurisdiction. This sovereign design is particularly relevant in fields such as medical research where privacy, regulation or intellectual property constraints limit the use of offshore cloud resources. Monash University Vice-Chancellor and President Professor Sharon Pickering with researchers [left to right] Professor Anton Peleg, Professor Victoria Mar, Professor James Whisstock, Vice-President (Strategy and Major Projects) Teresa Finlayson, and Professor Patrick Kwan.Eamon Gallagher (Australian Financial Review)Technically, the system reflects the latest shifts in high performance AI architecture. Built on NVIDIA GB200 NVL72 platforms and integrated using Dell’s rack scale infrastructure, MAVERIC employs closed loop liquid cooling to reduce water consumption compared with conventional air-cooled systems, aligning large scale compute growth with sustainability objectives while supporting high density, high throughput workloads.Professor James Whisstock, Deputy Dean Research of Monash’s Faculty of Medicine, Nursing, and Health Sciences commented, “MAVERIC provides a huge leap forward in our compute capability that will revolutionize our researchers’ ability to address the most challenging and important research questions across the fields of medical research, information technology, and STEM disciplines. It will seed wonderful new cross-disciplinary collaborations, underpin the work of our best and brightest young researchers and will allow our scientists to continue to make major discoveries that positively impact the Australian and global population more broadly.”“MAVERIC provides a huge leap forward in our compute capability that will revolutionize our researchers’ ability to address the most challenging and important research questions across the fields of medical research, information technology, and STEM disciplines.” —Professor James Whisstock, Deputy Dean Research of Monash’s Faculty of Medicine, Nursing, and Health SciencesMonash University frames MAVERIC not as a standalone asset, but as part of the national research infrastructure, intended to strengthen collaboration across academia, healthcare, government and industry. This approach positions Melbourne at the forefront of sovereign AI enabled research in the region.Data center scale as research infrastructureThe infrastructure demands of modern AI research extend well beyond individual systems. Melbourne’s expanding data center footprint now supports hyperscale compute, applied AI deployment and large-scale research workloads simultaneously. Total data center investment, US$ billions.Source: Data Centres Global Report 2025In February 2026, CDC Data Centres opened its first Melbourne campus in Brooklyn, with two live facilities and a third in planning. Combined with CDC’s Laverton campus, Melbourne is projected to host more than 800 megawatts of sovereign digital capacity, critical for AI workloads requiring sustained access to high-density power, cooling and secure environments.Parallel investment is underway in Fishermans Bend, where NEXTDC is developing a AUD $2 billion AI and digital infrastructure hub adjacent to the Innovation Precinct. Planned facilities include an AI Factory, a Mission Critical Operations Center and a Technology Center of Excellence, enabling sovereign AI, high-performance computing and cross-sector collaboration across health, defence and finance.Melbourne hosts Australia’s largest cluster of AI firms, with 188 companies, and more than 40 data centers currently operate across Victoria. The Victorian Government has complemented this growth with an initial AUD $5.5 million investment in the Sustainable Data Center Action Plan.Together, these developments reinforce Melbourne’s role as a national and increasingly global hub for high-performance AI infrastructure as model complexity and infrastructure dependency continue to accelerate.Applied AI research at scale Monash University is home to MAVERIC, Australia’s largest university-based AI supercomputer, built and deployed by Monash in partnership with NVIDIA, Dell Technologies, and CDC Data Centres.Monash UniversityMelbourne’s research strength is underpinned by a dense university network with deep capability across AI, data science and engineering. Institutions including Monash University, the University of Melbourne, Deakin University, La Trobe University, RMIT University and Swinburne University of Technology collectively support research across machine learning, robotics, human-computer interaction, extended reality and advanced manufacturing.This concentration fosters applied collaboration where AI intersects with medicine, sustainability, cognitive systems and immersive technologies. For visiting researchers, it provides access not only to academic expertise but also to live infrastructure environments where research can be tested and validated, reinforcing Melbourne’s position as one of the Asia-Pacific’s most integrated AI research ecosystems.Conferences as research accelerators Plenary session at Melbourne Convention and Exhibition Center.Melbourne Convention BureauMelbourne’s selection as host city for a growing number of international technology conferences reflects the convergence of research capability and infrastructure maturity.In September 2026, Data Center World Australia and The AI Summit Australia will be co-located at the Melbourne Convention and Exhibition Center, bringing together global leaders across AI, digital infrastructure and enterprise technology. The pairing highlights a broader reality: advances in AI are inseparable from the infrastructure that enables them.Melbourne’s expanding data center footprint now supports hyperscale compute, applied AI deployment and large-scale research workloads simultaneously.Research-led conferences are also expanding Melbourne’s global footprint. ICONIP 2026, hosted by Deakin University, will bring up to 700 researchers in neural networks and machine learning, followed in 2027 by IEEE VR, the leading conference on virtual reality and 3D user interfaces, attracting up to 1,000 delegates.In this context, conferences function not simply as events, but as infrastructure for knowledge transfer, supporting standards exchange, collaboration and system-level learning at global scale.A global platform for advancing researchSovereign compute, data center scale and a strong conference pipeline create a reinforcing cycle, enabling researchers to engage directly with infrastructure and industry well beyond the event itself.By closing the gap between theory and deployment, Melbourne supports deeper technical exchange and more enduring global research networks.This role was recognized in 2025 when the IEEE awarded Melbourne Convention Bureau the 2025 Organisational Supporting Friend of IEEE Member and Geographic Activities (MGA) — the first convention bureau in the Asia Pacific region to receive the acknowledgement as a result of the longstanding partnership with the IEEE Victorian Section. Melbourne Convention Bureau (MCB) representative Fatima Aboudrar, Senior Business Development Manager, with Vijay S. Paul, Immediate Past Chair, IEEE Victorian Section, receiving Supporting Friend Member recognition in 2025.As AI research becomes increasingly dependent on infrastructure scale, sovereign capability, and global collaboration, Melbourne is moving beyond hosting conversations to actively enabling the systems that advance AI and data‑driven research at global scale.Conference support in Melbourne Your browser does not support the video tag. Why host a conference in Melbourne, Australia.Melbourne Convention Bureau This ecosystem is underpinned by Melbourne’s highly accessible city center, where world-class venues, research institutions and industry hubs are located in close proximity. Free public transport and a compact city footprint enable seamless movement from conference floor to real-world application.Melbourne Convention Bureau (MCB) is a not-for-profit state government agency with over 60 years’ experience, that provides IEEE and its members with free support to bring international conferences to Melbourne, Australia. MCB’s support spans early-stage exploration and international bidding through to securing government funding, connecting organizers with venues, accommodation and event suppliers, and providing destination support for conference planning and delivery. Organizations considering a conference in Australia are encouraged to connect with MCB’s dedicated team, which supports IEEE conferences in Melbourne. Enquiries can be directed to info@melbournecb.com.au.

18.05.2026 10:00:01

Technologie a věda
10 dní

Editor’s note: If you’d like to pinpoint the instant when the world entered the nuclear age, 5:29:45 a.m. Mountain War Time on 16 July 1945, is an excellent choice. That was the moment when human beings first unleashed the power of the nucleus in an immense, blinding ball of fire above a gloomy stretch of desert in the Jornada del Muerto basin in New Mexico. Emily Seyl’s Trinity: An Illustrated History of the World’s First Atomic Test (The University of Chicago Press) offers hundreds of startlingly vivid photographs of the Manhattan Project that emerged from a 20-year restoration effort. This excerpt and the accompanying photos record the massive effort to capture the awesome detonation of “the Gadget.” aspect_ratioReprinted with permission from Trinity: An Illustrated History of the World’s First Atomic Test by Emily Seyl with contributions by Alan B. Carr, published by The University of Chicago Press. © 2026 by The University of Chicago. All rights reserved.In the North 10,000 photography bunker, Berlyn Brixner was listening to the countdown on a loudspeaker, his head inside a turret loaded with cameras and film. He was one of the only people instructed to look toward the blast—through his welder’s glasses—ready to follow the path of the fireball as it launched into the sky. The two Mitchell movie cameras at his station would deliver the best footage to come of the Trinity test, used by Los Alamos scientists to make some of the first measurements of the effects of a nuclear explosion.Related: New Trinity Book Uncovers Images of the First Atomic TestWhen the detonators fired, the cameras captured what Brixner could not have seen—the very first light of a violent, silent sea of energy unfurling into the basin. As 32 blocks of high explosives erupted all together, their incredible force surged inward toward the sleeping plutonium core, compressing the dense sphere of metal instantaneously from all sides and bringing its atoms impossibly close together. A carefully timed burst of neutrons sowed momentary, uncontrolled chaos, and then, as quickly as it began, the fission chain reaction ended. Footage from a high-speed Fastax camera in Brixner’s bunker, shot through a thick glass porthole, shows a translucent orb bursting through the darkness less than a hundredth of a second after detonation, as a rush of heat, light, and matter blew apart the Gadget.When the brightness faded enough for witnesses to make out ground zero, they saw a wall of dust rise up around a brilliant, shape-shifting, multicolored ball of flames—forming a fiery cloud that shot into the sky atop a twisting stream of debris. The camera footage tells a story no less dramatic but hundreds of times more intricate, preserving the moment for scientists to return to again and again to measure and describe the behavior of the fireball and other visible effects with exacting detail. On balance, the photography effort was a huge success, despite only 11 of the 52 cameras producing satisfactory images. By arranging those cameras at intentionally staggered distances, complementary angles, and with a broad spectrum of frame rates and focal lengths, the Spectrographic and Photographic Measurements Group was able to piece together a remarkably complete picture of their subject. On 12 July 1945, Herbert Lehr, a U.S. Army sergeant and electrical engineer assigned to Los Alamos, delivered the plutonium core to the McDonald ranch house, where the bomb was assembled. Los Alamos National LaboratoryAccording to the group’s leader, Julian Mack, the more than 100,000 frames that were captured still “give no idea of the brightness, or of time and space scales.” Mack attributed fortune, as much as foresight, to the photographic record that was made, especially during the earliest phase of the blast. Indeed, the explosion was several times more powerful than predicted, and the intensity of its effects overwhelmed many of the cameras and diagnostic instruments. The human observers were similarly overcome. “The shot was truly awe-inspiring,” said Norris Bradbury, the physicist who would succeed Robert Oppenheimer as director of Los Alamos. “Most experiences in life can be comprehended by prior experiences, but the atom bomb did not fit into any preconception possessed by anybody. The most startling feature was the intense light.” Norris Bradbury, the physicist responsible for the final assembly of the Gadget, stands next to the partially assembled bomb at the top of the shot tower. The cables on the outside of the bomb would transmit the signals to trigger the synchronized detonations of conventional explosives, which would then create the inward-directed shock wave that would compress the bomb’s plutonium core. Bradbury would go on to succeed Robert Oppenheimer as director of Los Alamos on 17 October 1945.Los Alamos National LaboratoryIt is a common sentiment that words and even pictures pale in comparison to the experience of the explosion. Even so, soldiers, scientists, and many other witnesses have added their firsthand accounts—often absorbing and poetic—to complement the trove of hard data collected during the test shot. They describe an intense and blinding brightness that filled the basin with daytime; an ominous, darkening cloud rearing its head in eerie silence; the wait for the invisible wave rushing out from the heart of the Gadget; and the mighty roar that arrived at last, in a thunder, and seemed never to leave. Physicist Isidor Isaac Rabi, watching from 20 miles away, remembered, “It blasted; it pounced; it bored its way right through you.”James Chadwick, head of the British contingent of scientists who joined the Manhattan Project, later said, “Although I had lived through this moment in my imagination many times during the past few years and everything happened almost as I had pictured it, the reality was shattering.” The blast, captured with an assortment of high-speed and motion-picture cameras, shows the fireball expanding between 25 milliseconds and 60 seconds, by which time the mushroom cloud is over 3 kilometers high.Los Alamos National LaboratoryAnd physicist George Kistiakowsky found himself certain that “at the end of the world—in the last millisecond of the Earth’s existence—the last human will see what we saw.”

15.05.2026 13:00:01

Technologie a věda
11 dní

The IEEE Communications Society (ComSoc)’s Research Collaboration Pitch Session initiative is proving to be a catalyst for meaningful engagement between academic researchers and industry innovators. Launched last year, the program connects promising researchers with industry leaders who can offer them funding, mentorship, and connections to bring interesting ideas closer to real-world deployment.Rather than relying on chance encounters at conferences, the pitch sessions create a focused environment. Five academic presenters share their work with five industry representatives, known as “innovation scouts”: senior leaders primarily chosen from ComSoc’s Corporate Program partner companies such as Ericsson, Intel, Keysight, and Nokia. The curated format ensures that each idea receives dedicated attention from professionals who are seeking new concepts aligned with their organization’s priorities.The initiative was launched in November at the IEEE Middle East Conference on Communications and Networking (MECOM) in Cairo and appeared in December at the IEEE Global Communications Conference (GLOBECOM) in Taipei, Taiwan.AI-driven communication networkOne of the most compelling outcomes came from the inaugural session in Cairo. Angela Waithaka, a student member and biomedical engineering student at Kenyatta University, in Nairobi, Kenya, presented her “AI-Driven Predictive Communication Networks for Enhanced Performance in Resource-Constrained Environments” paper. You can view her presentation along with others on IEEE.tv.Waithaka’s research tackles a critical challenge: Next-generation communication systems increasingly rely on artificial intelligence and machine learning, yet most existing architectures consume abundant computational and energy resources, which are not always present in developing regions.Waithaka proposed lightweight, adaptive AI/machine learning models capable of delivering predictive, reliable communication performance even under tight resource constraints.Her vision resonated with Ruiqi “Richie” Liu, a master researcher at ZTE in China. ZTE is a global leader in integrated information and communication technology solutions. Liu says he recognized the relevance Waithaka’s proposal had to his company’s work with the International Telecommunication Union. He invited her to establish an ITU account so she could participate in the organization’s meetings discussing global telecommunications standardization projects—which would elevate her work to an international stage.Simplifying data center protocolsThe momentum continued at GLOBECOM. Among the presenters was Nirmala Shenoy, a professor at the Rochester Institute of Technology, in New York. Shenoy, an IEEE member, spoke on the topic of simplifying data center network protocols. She highlighted the growing complexity of the critical networks, which underpin cloud services, enterprise IT, and emerging AI workloads.Shenoy’s focus on reducing protocol complexity while maintaining scalability, resilience, and low latency caught the attention of an innovation scout from Nokia, who heads its eXtended Reality Lab in Madrid. He found the key person at Nokia for Shenoy to connect with to discuss her research, and it led her to record a video for the company detailing her approach and its potential applications.A model for accelerating innovationThe early success stories demonstrate the power of intentional, structured engagement. By bringing researchers and industry leaders together in a format designed for discovery, ComSoc is helping accelerate innovation and expand opportunities for collaboration. The pitch sessions are not merely conference events; they are becoming a bridge between academic creativity and industry implementation.This year sessions will be held during the IEEE International Conference on Communications in Glasgow from 24 to 28 May, and more are scheduled during the IEEE International Mediterranean Conference on Communications and Networking in Sardinia from 6 to 9 July, and at GLOBECOM in Macau from 7 to 11 December.As the program continues to grow, it could become a signature ComSoc initiative, one that strengthens the research ecosystem, supports emerging talent, and ensures that promising ideas find pathways to real-world impact.

14.05.2026 18:00:02

Technologie a věda
11 dní

This sponsored article is brought to you by Applied Materials.At pivotal moments in history, progress has required more than individual brilliance. The most consequential breakthroughs — such as those achieved under the Human Genome Project — required a new operating paradigm: Concentrate the world’s best talent around a single mission, establish a common platform, share critical infrastructure, and collapse feedback loops. When stakes are high and timelines are compressed, sequential and siloed innovation simply cannot keep pace.Today’s AI era is creating an engineering race with similar demands. Every company is pushing to deliver higher-performance AI systems, faster. But performance is no longer defined by compute alone. AI workloads are increasingly dominated by the movement of data: In many cases, moving bits consumes as much — or more — energy than compute itself. As a result, reducing energy per bit can extend system‑level performance alongside gains in peak compute.The path to energy‑efficient AI therefore runs through system‑level engineering, spanning three tightly interconnected domains:Logic, where performance per watt depends on efficient transistor switching, low‑loss power, and signal delivery through dense wiring stacks.Memory, where surging bandwidth and capacity demands expose the memory wall, with processor capability advancing faster than memory access.Advanced packaging, where 3D integration, chiplet architectures, and high‑density interconnects bring compute and memory closer together — enabling system designs monolithic scaling can no longer sustain.These domains can no longer be optimized independently. Gains in logic efficiency stall without sufficient memory bandwidth. Advances in memory bandwidth fall short if packaging cannot deliver proximity within thermal and mechanical constraints. Packaging, in turn, is constrained by the precision of both front‑end device fabrication and back‑end integration processes.In the angstrom era, the hardest problems arise at the boundaries — between compute and memory in the package, front‑end and back‑end integration, and the tightly coupled process steps needed for precise 3D fabrication. And it is precisely this boundary‑driven complexity where the traditional innovation model breaks down.The Traditional R&D Workflow Is Too Slow for Angstrom‑Era AIFor decades, the semiconductor industry’s R&D model has resembled a relay race. Capabilities are developed in one part of the ecosystem, handed off downstream through integration and manufacturing, evaluated by chip and system designers, and only then fed back for the next iteration. That model worked when progress was dominated by relatively modular steps that could be scaled independently and simply dropped into the manufacturing flow.But the AI timeline has upended these rules. At angstrom‑scale dimensions, the physics enforces inescapable coupling across the entire stack: materials choices shape integration schemes; integration defines design rules; design rules dictate power delivery; wiring sets thermal budgets; and thermals ultimately constrain packaging scaling. System architects simply cannot wait 10–15 years for each major semiconductor technology inflection to mature.Representing a roughly $5 billion investment, EPIC is the largest commitment to advanced semiconductor equipment R&D in U.S. history.A long‑term perspective is essential to align materials innovation with emerging device architectures — and to develop the tools and processes required to integrate both with manufacturable precision. At Applied Materials, together with our customers, we are charting a course across the next 3–4 generations, extending as far as 10 years down the roadmap.The angstrom era demands that we break down silos and bring together the industry’s best minds — from leading companies to leading academic institutions. If the problem is coupled, the solution must be coupled. If the timeline is compressed, the learning loop must be compressed. It’s not enough to just innovate — we must innovate how we innovate.EPIC: A Center and Platform for High‑Velocity Co‑InnovationThis is the challenge that Applied Materials EPIC Center is designed to solve.Representing a roughly US $5 billion investment, EPIC is the largest commitment to advanced semiconductor equipment R&D in U.S. history. When it opens in 2026, it will deliver state‑of‑the‑art cleanroom capabilities built from the ground up to shorten the path from early‑stage research to full‑scale manufacturing. But the facilities are only one component of the model. EPIC is also a platform, an operating system for high-velocity co‑innovation that revolutionizes how ideas move from the lab to the fab. EPIC is a platform, an operating system for high-velocity co‑innovation that revolutionizes how ideas move from the lab to the fab.Applied MaterialsThe EPIC model compresses the traditional workflow. Customer engineers work side‑by‑side with Applied technologists from day one — moving beyond isolated process optimization and downstream handoffs. Within a shared, secure environment, EPIC tightly integrates atomistic modeling, test vehicles, process development, validation, and metrology feedback. Constraints that once surfaced late in development are identified and addressed early.The result is a potentially 2x faster path that benefits the entire ecosystem under one roof:Chipmakers gain earlier access to Applied’s R&D portfolio, faster learning cycles, and accelerated transfer of next‑generation technologies into high‑volume manufacturing.Ecosystem partners gain earlier access to advanced manufacturing technology and collaboration opportunities that expand what is possible through materials innovation.Academic institutions gain opportunities to strengthen the lab‑to‑fab pipeline and help develop future semiconductor talent.Building on decades of co‑development, we are reinventing the innovation pipeline with our partners across logic, memory, and advanced packaging to deliver the next leap in energy‑efficient AI.Accelerating Advanced LogicLogic remains the engine of AI compute. In the angstrom era, however, system‑level gains are increasingly constrained by power and energy. Extending AI performance now depends on architectures that deliver more performance per watt — accelerating the move to 3D devices such as gate‑all‑around (GAA) transistors, which boost density within a compact footprint while preserving power efficiency. Architectures that deliver more performance per watt are accelerating the move to 3D devices such as gate‑all‑around (GAA) transistors, and further out, complementary FETs (CFETs), which push density scaling even more.Applied MaterialsThese architectural shifts are unfolding at unprecedented scale, with the logic roadmap already extending beyond first‑generation GAA toward more advanced designs. One key example is GAA with backside power delivery, which relocates thick power lines to the backside of the wafer, reducing resistive losses and freeing front‑side routing for tighter logic cell integration. Another example brings adjacent GAA PMOS and NMOS transistors closer together while inserting a dielectric isolation wall between them to minimize electrical interference. Further out, complementary FETs (CFETs) push density scaling even more by stacking PMOS and NMOS devices directly atop one another.While these architectures deliver compelling gains in performance per watt and logic density without relying solely on tighter lithography, they significantly raise integration complexity. Manufacturing a single GAA device today can involve more than 2,000 tightly interdependent process steps. At the same time, wiring stacks continue to grow taller and denser to connect these advanced logic devices. Modern leading‑edge GPUs now in development pack more than 300 billion transistors into an area little larger than a postage stamp, interconnected by over 2,000 miles of wiring. Modern leading‑edge GPUs now in development pack more than 300 billion transistors into an area little larger than a postage stamp, interconnected by over 2,000 miles of wiring.Applied MaterialsAt this level of complexity, the process steps used to create these precise 3D devices and wiring stacks cannot be optimized independently. Design and process must evolve in lockstep, and materials innovation and fabrication methods must advance alongside device architecture. EPIC’s co‑innovation model is designed to accelerate exactly this convergence — enabling logic compute to continue advancing the frontiers of AI at the pace the roadmap demands.Powering the Memory RoadmapAt the same time, the AI computing era is fundamentally reshaping how data is generated, moved, and processed — making memory technologies, especially DRAM, central to delivering the energy‑efficient performance AI systems require. As models grow larger and more data‑hungry, the DRAM roadmap is shifting toward architectures that deliver higher density, greater bandwidth, and faster access per watt. At the DRAM cell level, AI performance requirements are driving a transition from 6F² buried‑channel array transistors (BCAT) to more compact 4F², and beyond that, architectures that move past what 2D scaling alone can deliver. Applied MaterialsAt the DRAM cell level, this shift is driving a transition from 6F² buried‑channel array transistors (BCAT) to more compact 4F² architectures, which orient the transistor vertically to boost density and reduce chip area. Looking beyond 4F², sustaining gains in performance per watt will require moving past what 2D scaling alone can deliver. The industry is therefore turning to 3D DRAM, stacking memory cells vertically to add capacity within a constrained footprint. As these structures grow taller and aspect ratios intensify, high-mobility materials engineering in three dimensions becomes increasingly critical to performance and reliability.Beyond the memory cell array, another powerful lever for DRAM scaling is shrinking the peripheral circuitry, which includes logic transistors and interconnect wiring. One emerging approach places select periphery functions beneath the DRAM array by bonding two wafers — one optimized for the DRAM cells and the other for CMOS logic — using multiple wiring layers. Beyond the memory cell array, another powerful lever for DRAM scaling is shrinking the peripheral circuitry, which includes logic transistors and interconnect wiring.Applied MaterialsIn parallel, DRAM performance is being extended by leveraging logic‑proven enhancers in the memory periphery. These include mobility boosters such as embedded silicon germanium and stress films, along with wiring upgrades like improved low‑k dielectrics and advanced copper interconnects. Memory manufacturers are also transitioning periphery transistors from planar devices to FinFET architectures, following the logic roadmap to further improve I/O speed. These valuable inflections are central to EPIC’s mission — where they can be co-developed and rapidly validated for next‑generation memory systems.Driving System Scaling With Advanced PackagingAs data movement becomes the dominant energy cost in AI systems, advanced packaging has emerged as a critical lever for improving system‑level efficiency—shortening interconnect distances, increasing bandwidth density, and reducing the power required to move data between logic and memory. The rise of 3D packages such as high‑bandwidth memory (HBM) underscores why advanced packaging is becoming central to the AI era.Applied MaterialsHigh‑bandwidth memory (HBM) marks a major inflection along this path. By stacking DRAM dies — scaling to 16 layers and beyond — and placing memory much closer to the processor, HBM enables rapid access to ever‑larger working datasets. This delivers step‑function gains in both bandwidth and energy efficiency.More broadly, the rise of 3D packages such as HBM underscores why advanced packaging is becoming central to the AI era. Packaging now addresses system‑level constraints that logic and memory device scaling alone can no longer overcome. It also enables a move away from monolithic systems‑on‑chip toward chiplet‑based architectures, as AI workloads increasingly demand flexible designs that combine logic, memory, and specialized accelerators optimized for specific tasks.A vital technology powering this roadmap is hybrid bonding. With interconnect pitches approaching those of on‑chip wiring, conventional bumps and microbumps run into fundamental limits in density, power, and signal integrity. Hybrid bonding removes these barriers by allowing dramatically higher interconnect and I/O density, supporting a broad range of chiplet architectures — from memory stacking to tighter compute‑memory integration. EPIC tackles high‑value advanced‑packaging challenges through early, parallel co‑innovation across materials, integration, and manufacturing.Applied MaterialsAs bonded structures like HBM stacks grow larger and more complex, warpage control, die placement, stack alignment, and thermal management become first‑order challenges. EPIC tackles these and other high‑value advanced‑packaging challenges through early, parallel co‑innovation across materials, integration, and manufacturing.Bringing It All TogetherAcross logic, memory, and advanced packaging, our industry faces an ambitious roadmap that promises significant gains in energy efficiency for AI systems. But realizing that potential demands breakthrough materials innovation at a time when feature sizes are shrinking, interfaces are multiplying, and process interdependencies are escalating. These challenges cannot be solved on 10–15‑year timelines under the traditional relay‑race model. We must break down silos, align earlier across the ecosystem, and parallelize learning to keep pace with AI’s demands.In the AI era, progress will be defined by the speed at which lightbulb moments turn into manufacturing and commercialization reality. The only viable path forward is a new innovation model — and EPIC is how we are driving it.

14.05.2026 10:00:01

Technologie a věda
13 dní

Given how integral the Internet has become to everyday tasks such as shopping, paying bills, and holding virtual meetings, it’s interesting that nearly 30 percent of the global population still has no access to it. More than 2 billion people are still offline, according to a report released in November by the International Telecommunication Union.More and more people are being connected, though, thanks to IEEE Future Networks’ Connecting the Unconnected (CTU) and similar programs. Since 2021, the technical community has been working to accelerate the development, standardization, and deployment of 5G, 6G, and future generations.Every year, CTU holds a worldwide competition to seek out innovators who are in the early stages of developing technologies or applications to provide greater access. It also holds an annual summit that brings together experts, community leaders, and other interested parties to discuss strategies to expand access and foster digital inclusion.CTU expanded in several ways last year. It launched regional summits to focus on local connectivity issues, organized community-focused events, and established an expanded mentorship program to further support contest winners and the next generation of technological innovators impacting humanity. The program also partners with the IEEE Standards Association (IEEE SA) to develop guidelines for some of the submitted innovations.“IEEE Future Networks has created a community to bring all these initiatives working on digital connectivity together in a single platform and leverage the IEEE brand to help raise the visibility of their work,” says IEEE Life Fellow Sudhir Dixit, a CTU cochair and a Basic Internet Foundation cofounder, which also works to expand Internet access.A contest for new connectivity methodsThe CTU challenge, launched in 2021, typically receives 200 to 300 submissions each year, Dixit says. Last year 245 projects from 52 countries were submitted. Participants include academics, nonprofit organizations, startups, and students.Projects can be entered into one of three categories. The Technology Applications category is for new connectivity methods or innovations that broaden broadband access. Those who improve the affordability of Internet services can enter the Business Model category. The Community Enablement category is for strategies that promote public broadband adoption.After selecting a category, entrants choose between two tracks based on their project’s maturity. The proof-of-concept route is for early-stage but functional technology that has already produced results. The conceptual path is for projects in the theoretical phase that have not undergone full testing.“IEEE Future Networks has created a community to bring all these initiatives working on digital connectivity together in a single platform and leverage the IEEE brand to help raise the visibility of their work.” —Sudhir Dixit, Connecting the Unconnected cochairLast year’s challenge submission period was from March to June, with judging phases from June through November. The 20 winners presented their solutions in December at a virtual Winners Summit. Fourteen projects received prize money, ranging from US $500 to $2,500. Six finalists earned an honorable mention at the summit.The awards amounts have varied over the years, based on the sponsorship.Among the winners were a solar-powered community broadband network in Tanzania, a low-cost method for accessing the Internet that uses FM radio and a short message service (SMS), and a strategy for utilizing India’s rural broadband infrastructure to deliver medical services to people living in isolated, tribal, and other underserved regions.“Our job is to help further develop the technology, look for gaps, and see if it is good enough to be applied to rural villages, like those in Africa and India,” says IEEE Fellow Ashutosh Dutta, who is a CTU cochair and a professor at Johns Hopkins University, in Baltimore. “The idea behind the contest is to make sure the technology actually gets implemented at the grassroots level and is being used by the local community.”This year’s challenge submission period runs until 19 June, with judging phases from July through October. The finalists of the 2025 IEEE Connect the Unconnected challenge describe their projects.IEEE Future NetworksLocal connectivity discussionsThe CTU program hosted three regional summits last year. The North American event was held in September in Washington, D.C. In November, the Global/Asia-Pacific meeting took place in Bangalore, India; it was co-located with the IEEE Future Networks World Forum. The Europe, Middle East, and Africa summit also was held in November, in Abuja, Nigeria.Topics discussed at the summits included infrastructure solutions for universal connectivity; sustainable business models; scaling homegrown technologies; and policy, regulation, and financing issues.As of press time, the dates for this year’s regional summits had not been announced.Community-focused eventsTo help bridge the gap between ideas and their deployment, the Connect a Community event was established to demonstrate how some new technologies might benefit people. The inaugural event was held in November in Bengaluru, India. During the daylong program, 10 of the challenge winners demonstrated their connectivity solutions to villagers from seven rural communities.Dutta credits IEEE Life Fellow Rakesh Kumar with devising the event. Kumar chairs IEEE Future Directions, which was where Future Networks got its start in 2017 as the 5G Initiative.“Kumar wants to ensure the winning technologies are going to be useful for the community,” Dutta says.Providing entrepreneurs with business skillsDixit says the Future Networks team believed that simply conducting a competition and distributing prizes wasn’t enough.“We wanted to follow up with the winners, monitor their progress, and help them turn their ideas into a business,” he says.To accomplish that, IEEE launched the Empowerment Through Mentorship program, in which budding entrepreneurs are paired with industry leaders and experienced mentors who provide them with 1,000 days of guidance, coaching them on scaling up their business.“We launched the mentorship program to further the cause,” Dixit says. “These people may be good at developing technology, but they don’t know the marketing challenges, how to raise money, and other factors.”The Lemelson Foundation, an organization in Portland, Ore., that partners with IEEE, collaborated on the mentorship program. The foundation’s philanthropic strategy is to cultivate a robust ecosystem for entrepreneurs in East Africa, India, and the United States. It does so by providing the entrepreneurs with tools including financing options and access to communities that share their passion.The foundation chose to partner with IEEE “because of its powerful international network and focus on electrical engineering, which is a critical element of communications and energy infrastructure globally,” says Kory Murphy, Lemelson’s program officer for U.S. invention and entrepreneurship.“Other factors include IEEE’s focus on nontraditional or disadvantaged areas in India,” Murphy says, “and its recognition that mentorship is critical for the successful deployment of new technologies.”IEEE began an early pilot project in 2023 with support of a grant from the Lemelson Foundation, to determine if a sustained entrepreneurship mentorship program was valuable and necessary, he says. It then conducted a survey through 2024 to collect information to better understand the needs of stakeholders, mentors, and entrepreneurs in hard-to-reach areas in India. While the early pilot program was restricted to that country, its intent was to learn from the experience and share the findings globally, he says.“Our job is to help further develop the technology, look for gaps, and see if it is good enough to be applied to rural villages, like those in Africa and India.” —Ashutosh Dutta, Connecting the Unconnected cochair “The foundation’s involvement was aimed at testing certain activities, partnership strategies, and understanding the budgetary requirements for a prepilot program,” he says. “The primary goal of the foundation is to enable conditions for innovation to occur within regional systems, especially addressing the opportunity for sustained, systematic, and relational mentorship in technology innovation.”The Empowerment Through Mentorship program is structured into three tiers. One focuses on individuals and their needs, the program/technical level focuses on the invention, and the venture level guides participants from the initial concept through product testing and validation. Within each track, participants engage in activities such as networking, securing financial support, and pitching their innovations, Murphy says.“The 1,000-day approach reflects the belief that it requires a long period of time to coach and support those who traditionally are excluded,” he says.CTU mentors can be IEEE members or nonmembers who are successful entrepreneurs and own small or large companies, Dixit says. They also can work in academia.“They need to be passionate about training and mentoring other people,” Dixit says. “We have created a curriculum that covers topics such as ways to get financing from investors and how to turn ideas into a profitable business. It’s not the technology that will make the product successful; it’s everything else that goes into it.”Rural broadband architecture standardsTo determine whether any of the challenge’s submitted projects have the potential to become a standard, the CTU working group collaborates with the IEEE SA Industry Connections program’s 6G Rural Connectivity and Intelligent Village activity. Projects considered for standards do not have to be winners. Any project that has successfully passed the first phase, completed the second-phase requirements, and requested a review may be considered.Typically, about half of the submitted projects are reviewed for possible standard implications, Dutta says.“We selected about 60 submissions that could be potentially standardized,” he says. “Out of those, we work with IEEE SA’s rapid reactive standards activity group to narrow them down to five or 10 that can be potentially standardized.“The CTU program is not only about developing a technology or implementing it, but also standardizing it so that people around the world can use the standard.”One such project led to the development of IEEE P1962, “Standard for Providing Broadband Connectivity to Rural Infrastructure by Utilizing Solar Panels as Optical Communication Receivers.” It specifies an architecture for an optical receiver that uses solar panels and associated circuitry to provide energy-efficient, affordable, and high-speed optical wireless communication.“CTU has created a platform for the world to bring their ideas to one single place where people can talk to each other about them,” Dixit says. “We are a unifying force.We bring these many dimensions together to connect the unconnected.”CTU Challenge Winner: Community Radio BoloThe Connecting the Unconnected program offers contestants benefits that extend beyond the recognition and rewards. One participant who benefited is Ritu Srivastava, a telecommunications engineer and IEEE member. She placed first in the 2022 technical concept category for her project, Community Radio Bolo (CR Bolo). The verb bolo means speak in Hindi.Internet services in India’s rural areas are either unavailable or have spotty coverage. People there rely on community radio stations to get news about local events and issues. There are about 300 such stations in India, Srivastava says.To provide broadband Internet access in the Bhadrak district of Odisha, India, she developed a cost-effective hybrid network that uses an online and offline wireless mesh network installed on the tower of community radio station Radio Bulbul. Several transceiver locations, known as access points, are located at schools and community centers that are within a 5- to 7-kilometer radius, connecting them with Radio Bulbul.CR Bolo includes a plug-and-play interactive voice response system that is coupled with the hybrid wireless network. The automated telephony technology routes callers using voice commands or a telephone’s keypad to the appropriate department. The system also has a direct-to-consumer platform where manufacturers sell their products through websites or mobile apps.“CR Bolo is a unique method of leveraging rural traditional technologies and infrastructure combined with modern technology to provide meaningful access to communities,” Srivastava says, “improving livelihood opportunities and creating social and economic viability for CR stations.”She says she plans to expand the project to other rural communities in India. She will incorporate a large language model and offer a learning management system to deliver training programs and educational courses, she says.Winning CTU inspired her to become a more active IEEE volunteer, she says. She is working with the IEEE Standards Association to develop guidelines for the architecture of broadband technology used in rural areas.Because of her entrepreneurial experience, CTU hired her in 2023 to assist with the challenge and the Empowerment Through Mentorship program.Srivastava is a director at Jadeite Solutions in New Delhi. The consulting company offers nonprofit organizations that are developing socioeconomic programs with project evaluation, impact assessment, financial reviews, and similar services.She credits CTU with giving her and her community-centered model more exposure: “The CTU challenge has given me a lot of other opportunities in terms of networking, funding resources, publishing my research in IEEE journals, and presenting at national and international conferences.”

12.05.2026 18:00:02

Technologie a věda
13 dní

This sponsored article is brought to you by Ampace.As AI workloads grow to gigascale levels, the global data center industry has hit a hidden physical wall. The real bottleneck is no longer just the thermal limit of the chip or the capacity of the cooling system — it is the dynamic resilience of the power chain.Modern AI computing clusters, driven by massive GPU clusters, generate high-frequency, abrupt, and synchronized spikey pulse loads. As rack densities soar beyond 100 kW, these fluctuations are amplified into a “power paradox”: while the digital logic of AI is moving faster than ever, the physical infrastructure supporting it remains tethered to legacy response capabilities.The power usage of these gigascale sites and their drastic, high frequency, abrupt load surges from the AI GPU clusters can trigger transient voltage events and frequency instability, risking the entire local grid. The grid itself is not robust enough to support these loads. This leads to the infrastructure gap: The utility is not robust enough and traditional backup sources, such as diesel generators and gas turbines, simply cannot react to millisecond-level power spikes in output. This will often force operators into a cycle of costly infrastructure over sizing just to buffer the volatility.AI infrastructure requires energy systems capable of instantaneous response while safeguarding continuity and reliability.The industry has explored various mitigations — from rack-level BBUs to 800V DC architectures — yet the mature, high volume, traditional UPS system remains the most viable and scalable foundation for gigawatt-level facilities. Consequently, the UPS-integrated battery system has emerged as the critical “physical buffer” to neutralize these pulses at the source.At Data Center World 2026 in Washington, D.C., Ampace led a pivotal technical dialogue with Eaton during the session “Powering Giga-scale AI.” Their exchange unveiled a fundamental paradigm shift: To bridge the AI power gap, energy storage must evolve from a passive insurance policy into an active, high-speed stabilizer. By aligning Ampace’s semi-solid-state battery innovation with Eaton’s proven system intelligence, we are moving beyond simple backup to solve the physical paradox of the AI era. To move beyond simple backup and solve the physical paradox of the AI era, Ampace is aligning its semi-solid-state battery innovation with Eaton’s proven system intelligence.AmpaceThe “Shock Absorber” physics: semi-solid chemistry for AI pulsesConventional power systems were designed for steady-state loads, not the rapid heartbeat of a massive AI GPU cluster. When thousands of GPUs synchronize their computing cycles, they generate high-frequency, abrupt pulse loads that can lead to voltage sags, frequency oscillations, and potential interruptions of critical AI training.Ampace’s PU Series semi-solid and low-electrolyte cells address this challenge by acting as high-speed “shock absorbers.” Leveraging ultra-low internal resistance (DCR) and high cycle capability, these batteries neutralize millisecond-level power spikes at the source, stabilizing the local power loop before disturbances propagate upstream to the grid or on-site generators. These high-rate cells enable 100 kW+ racks to maintain peak performance without transmitting instability across the power chain.This capability aligns closely with Eaton’s matured UPS architectures, such as double-conversion topologies and advanced power electronics upgrades, which have long prioritized rapid load responsiveness and high system stability.Together, these approaches embody a shared industry philosophy: AI infrastructure requires energy systems capable of instantaneous response while safeguarding continuity and reliability. Ampace’s semi-solid state chemistry minimizes liquid electrolyte, greatly reducing the risk of leakage and thermal runaway under continuous AI high-load conditions.AmpaceAlgorithmic intelligence: synchronizing energy and controlHardware alone cannot solve the AI power paradox; the system also requires intelligent coordination between energy storage and power management. Sophisticated battery management systems (BMS) like Ampace’s high-precision design track state-of-charge (SOC) with high-speed sampling, even during rapid, shallow cycling typical in AI workloads.Complementary algorithmic approaches in modern UPS platforms — such as ramp-rate control and average power management — effectively suppress sub-synchronous oscillations and optimize load smoothing. In large-scale AI training environments, where thousands of GPUs can trigger millisecond-level power pulses, these intelligent layers ensure that batteries buffer high-frequency fluctuations without compromising the mandatory emergency backup reserves.By transforming energy storage from passive “standby insurance” into active, schedulable assets, the system simultaneously safeguards continuous AI training and maintains the long-term health of the data center infrastructure. In practical terms, this means that even during peak compute bursts, the infrastructure remains stable, training cycles continue uninterrupted, and operators avoid costly oversizing or grid stress.Eaton’s dual-layer algorithms serve as a valuable benchmark in this space, demonstrating how advanced control logic can achieve similar objectives, reinforcing Ampace’s approach and philosophy within the broader data center power ecosystem.Economic scalability: optimizing AI infrastructure efficientlyOne of the largest costs in deploying AI infrastructure is “oversizing”: procuring transformers, generators, and UPS systems to handle brief peak spikes. This traditional approach inflates the Total Cost of Ownership (TCO) and leads to wasted capital on underutilized hardware.Ampace’s turn-key cabinet design developed by its independent R&D is engineered for seamless compatibility with mature, high volume UPS systems. By leveraging Eaton’s double-conversion UPS topologies alongside intelligent ramp-rate and average power management algorithms, AI data centers can scale dynamically without requiring costly infrastructure redesigns. This approach allows the UPS and batteries to act as active load-shapers, smoothing AI-driven pulses while strictly maintaining mandatory emergency backup capacity.By utilizing energy storage as an active, schedulable asset, operators can right-size their infrastructure, avoid unnecessary grid upgrades, and deploy gigascale AI clusters with unprecedented efficiency.Safety First: Protecting AI Infrastructure While Enabling InnovationIn high-density AI facilities, safety is non-negotiable. Ampace’s semi-solid state chemistry minimizes liquid electrolyte, greatly reducing the risk of leakage and thermal runaway under continuous AI high-load conditions. Ampace’s turn-key cabinet design developed by its independent R&D is engineered for seamless compatibility with mature, high volume UPS systems. AmpaceAt the same time, Eaton’s UPS design emphasizes system-level energy scheduling that never sacrifices mandatory emergency backup reserves, ensuring thermal safety and uninterrupted operation.This “safety-first” approach ensures that infrastructure can sustain aggressive performance targets without compromising the physical integrity of the facility. Coupled with over a decade of proven high-cycle life operation and design under shallow pulse conditions, these systems can extend operational lifespan, reduce replacement requirements, and provide operators with confidence that safety and reliability remain uncompromised as compute density continues to grow.To remain the scalable backbone of AI data centersAs AI computing scales over the next two to three years, the industry will face stricter grid requirements and even more demanding pulse load characteristics. This evolution demands a forward-looking design philosophy that harmonizes UPS, battery, and grid compatibility.Ampace views current low-electrolyte semi-solid technologies as the optimal transitional step toward a fully solid-state future — one that promises ultimate safety and performance.Ampace remains committed to this long-term technological roadmap. We view current low-electrolyte semi-solid technologies as the optimal transitional step toward a fully solid-state future — one that promises ultimate safety and performance. Whether through rack-level BBU, integrated UPS systems, or containerized storage, the universal core of the AI era remains constant: high-speed response, long shallow-cycle life, and refined energy management.By engaging in deep technical exchanges with Eaton and leading energy innovators, Ampace ensures that its solutions not only meet today’s AI pulse challenges but also harmonize with broader infrastructure strategies and shared industry best practices.Ultimately, as traditional diesel generators gradually give way to diversified alternatives, the integrated UPS-plus-energy-storage system will become the fundamental infrastructure standard.The dialogue has just begun. Ampace will continue to engage in strategic exchanges with global industrial automation leaders and digital energy pioneers, co-authoring the playbook for a safer, more efficient, and more resilient AI-ready world.

12.05.2026 17:15:15

Zahrádkaření

Zprava i zleva

Zprava i zleva
3 dny
Zprava i zleva
4 dny

As colleges hold graduation ceremonies across the country, many schools are attempting to silence pro-Palestine speech at the commemorations, including canceling speakers and eliminating live speeches by students altogether. There will be no live student speakers at the City University of New York’s School of Law or at New York University’s school-specific ceremonies after former students gave speeches that included expressing support for Palestine and criticism of Israel. Rutgers University canceled biotech CEO Rami Elghandour’s commencement speech at its School of Engineering’s convocation, citing complaints about his social media posts on Israel and Palestine. And the University of Michigan’s president issued a public apology after professor Derek Peterson praised pro-Palestine students during his commencement address. “Our students are being told that your families, your Palestinian families, are expected to suffer and die, and you should be OK with it,” says Noura Erakat, a Palestinian human rights attorney and professor at Rutgers University. Erakat adds that Rutgers professors have been asked not to teach about the conditions in Gaza. “We are asked to betray the empirical record, including the one on genocide and apartheid, and we refuse to do that.” “This will be the third graduation and commencement ceremony in a row where we do not have a student speaker, we do not have a faculty speaker and we do not have a live-stream commencement,” says Shivani Desai, a member of CUNY Law Students for Justice in Palestine. “They took all of that away from us, and they took that away specifically because of Palestine repression.”

21.05.2026 08:41:04

Zprava i zleva
4 dny

The Trump administration is advancing plans to resettle an additional 10,000 white South Africans in the United States as refugees. Under President Trump’s proposal, which was submitted to Congress on Monday, the U.S. would lift its record-low refugee admissions figure from 7,500 to 17,500, with the additional openings reserved for Afrikaners. This comes as the administration continues to block the entry of refugees from other countries. The U.S. has resettled just over 6,000 refugees between October and April — all except three were from South Africa. Trump has said Afrikaners face racial persecution and genocide in South Africa, claims that have been rejected by the U.N. Human Rights Office, among others. Last year, he cut off aid to the country and boycotted the G20 summit in Johannesburg. “Whiteness is being recast as endangered,” says Lebohang Pheko, a professor of practice at the University of Johannesburg. “There is a move towards the alt-right, the MAGA discourse, which is about replacement theory, and which is absolutely about displacing the idea that anything other than whiteness is normative.” Pheko also suggests that Trump’s actions toward South Africa are retribution for the genocide case it brought against Israel at the International Court of Justice. “We are processing resettlement cases for white Afrikaners at a record pace,” adds Sharif Aly, president of the International Refugee Assistance Project, which is currently litigating a class-action lawsuit challenging the Trump administration’s dismantling of the United States refugee program. “This program has never been a fast program, and it’s being expedited for just this one population.” While Afrikaners are being quickly resettled, “thousands of other people who have went through years of vetting, who have went through years of persecution and violence,” are being blocked from entering the U.S., says Aly.

21.05.2026 08:13:48

Zprava i zleva
7 dní
Zprava i zleva
7 dní

Thousands of people gathered on the National Mall in Washington, D.C., on Sunday for “Rededicate 250,” a taxpayer-funded Christian evangelical service backed by President Trump. The eight-hour lineup featured songs, prayers and remarks by top government officials including Secretary of State Marco Rubio, House Speaker Mike Johnson and Defense Secretary Pete Hegseth. The event included religious leaders like evangelist Franklin Graham and Cardinal Timothy Dolan. “Nothing was Christian about what we saw yesterday,” says Bishop William J. Barber II. “This is idolatry. This is heresy. This is a form of religious nationalism. This is Trump worship. This is trying to make someone a messiah figure.” Barber, the president of Repairers of the Breach and founding director of the Yale Center for Public Theology and Public Policy, took part in a counter-event on Sunday called Redirect 250. “This is really a battle for the soul of America,” says Sarah Posner, author of Unholy: How White Christian Nationalists Powered the Trump Presidency, and the Devastating Legacy They Left Behind. The Supreme Court has eroded the separation of church and state in recent decades, particularly under President Trump, adds Posner. She also notes that “evangelicals, for decades, have been marinating in Christian Zionist theology and ideology, which holds that, in their view, America has a biblical duty to defend Israel, and in particular defend Israel from aggression, both nuclear and otherwise, from Iran.”

18.05.2026 08:26:32

Zprava i zleva
10 dní

We speak to two prominent Israeli thinkers, historian Omer Bartov and journalist Gideon Levy, about the founding beliefs of Zionism. Bartov, a professor of Holocaust and genocide studies at Brown University, is the author of the new book Israel: What Went Wrong? Bartov says the early Zionist movement had liberatory intentions, aiming to emancipate the persecuted Jewish minority in Europe and modeling itself after other contemporary ethnonationalist movements. He then argues that while Israel had the opportunity to “become a normal state” and “issue a constitution that would provide equality to all its citizens, would define its borders and create a legal framework” that could also acknowledge and redress the Nakba, it chose another path. Instead of remedying its foundational violence, he says, the modern Israeli state has become increasingly “militaristic, centralized, expansionist, racist and, as we’ve seen since October 2023, genocidal.” Though Bartov does not identify as an anti-Zionist, he says Israel “must discard Zionism, it must put it on the garbage heap of history, and it must redefine itself, going all the way back to 1948.” Levy, on the other hand, says Zionism has never been reformable, because the movement, from its very beginning, “started wrong, without the belief or the conviction that we can live together.” He contests Bartov’s assertion that early Zionist intentions became warped over the 20th century, and says instead that the violent dispossession of Palestinians is embedded into the premise of the movement. “This very same attitude, this very same policy never stopped ever since ’48,” Levy contends. His latest piece in Haaretz is titled “Zionism Didn’t Go Wrong, It Was Always Built This Way.” Both Bartov and Levy also respond to the Israeli government’s threat to file a defamation lawsuit against The New York Times for publishing a column by longtime opinion writer Nicholas Kristof about systemic sexual abuse against Palestinian detainees in Israeli prisons. “That has become the policy of the country — to abuse, to humiliate, to rape systematically,” says Bartov. Levy explains Israel’s reaction “is to attack the messenger.”

15.05.2026 08:35:58

Zprava i zleva
10 dní

Palestinians around the world are marking Nakba Day, 78 years after their forced mass displacement led to the establishment of the Jewish-majority state of Israel. Decades later, Palestinians still face widespread oppression and violence from the Israeli state as it continues its expansionary project. “Israel tried, since 1948 until today, to destroy us as a people, as a group, and they failed at it. Our people are still there, resilient,” says Palestinian writer Muhammad Shehada, who was born in Gaza and now lives in Denmark. Shehada discusses the ongoing process of the Nakba, including its latest intensification after October 7, 2023. “Now this veneer of civility has fallen off. The mask was taken off. And now it’s a matter of national pride in Israel to brag about annihilating Palestinians.” Shehada also describes current conditions in Gaza — still under Israeli blockade and occupation — and what he calls the “disarmament trap” of unfairly weighted negotiations designed to strip Palestinians of political autonomy. “The 'realistic' proposal that Israel is putting on the table is surrender, capitulate, become fully defenseless, weaponless, and entrust the very army that carried out a genocide against you to be merciful towards you once you are an easier target than you ever were before.” Finally, he responds to the Israeli government’s recent threat to file a defamation lawsuit against The New York Times, after the paper published a column by longtime opinion writer Nicholas Kristof about systemic sexual abuse against Palestinian detainees in Israeli prisons. “It’s the newspaper of record. It’ll be spread and disseminated widely to an American audience,” says Shehada about the allegations levied in Kristof’s piece. “So we see, basically, an Israeli panic attack in return.”

15.05.2026 08:15:56

Zprava i zleva
11 dní

U.S. President Donald Trump is in Beijing for a highly anticipated summit with his Chinese counterpart President Xi Jinping. It is the first U.S. state visit to China since 2017, during Trump’s first administration. Trade, the Iran war, artificial intelligence and the fate of Taiwan are some of the issues being discussed, although it’s not clear if any new agreements are likely. Trump traveled to China with Secretary of State Marco Rubio, Defense Secretary Pete Hegseth and Treasury Secretary Scott Bessent, along with a delegation of top U.S. executives including Apple CEO Tim Cook, Elon Musk of Tesla and Jensen Huang of Nvidia. The summit comes after years of rising hostility between the two superpowers, but leaders recognize the importance of improving the bilateral relationship, says Zhao Hai, director of international political studies at the Institute of World Economics and Politics in Beijing. “This is a very critical historical moment [at] a crossroad, and both sides now are working together to establish a stable relationship that will have a global ramification,” he says. We also speak with Jake Werner, a historian of modern China and director of the East Asia Program at the Quincy Institute for Responsible Statecraft. He says the U.S.-Israeli war on Iran and the resulting economic chaos have strengthened China’s position. “China has ties to all the countries in the region. It has acted in the past to help broker the normalization of relations between Saudi Arabia and Iran,” says Werner. “So it has some experience in this realm, sort of acting as a broker towards peace.”

14.05.2026 08:15:40

Zprava i zleva
12 dní

Trump’s commissioner of the Food and Drug Administration, Dr. Martin Makary, has resigned. During Makary’s 13-month tenure, he attempted to split the difference between Health and Human Services Secretary Robert F. Kennedy Jr.’s Make America Healthy Again agenda and a more traditional approach to regulation, ultimately angering both camps. “Nobody was happy with what he did,” says Dr. Aaron Kesselheim, a professor of medicine at Harvard Medical School. Shortly before his resignation, Makary had drawn the ire of President Trump for attempting to block the approval of fruit-flavored vapes, and anti-abortion groups for not placing harsher restrictions on the abortion pill mifepristone. But even before Makary took the helm, mass layoffs and the loss of scientific expertise had already thrown the FDA, which has oversight powers extending to more than a fifth of the U.S. economy, in turmoil. The FDA’s deputy commissioner for food, Kyle Diamantis, will now assume Makary’s position in an acting capacity. Diamantas, a personal friend of Donald Trump Jr., does not have a background in medicine. The abrupt leadership shakeup is worrisome for the future of health and medicine in the United States, says Dr. Robert Steinbrook, the health research director at watchdog organization Public Citizen. “We need a strong public health agency,” he explains. “[But] when you pick them apart for particular theories and the idiosyncrasies of the Health and Human Services secretary, you destroy things which take years, if not decades, to rebuild.”

13.05.2026 08:13:12

Zábava