|
PolarScanMatching(PSM)
1
|
Go to the source code of this file.
Functions | |
| void | dr_init (int screen_x_max, int screen_y_max, double xmin, double ymin, double xmax, double ymax) |
| Initialize the drawing module. More... | |
| void | dr_close (void) |
| Close the drawing window. More... | |
| void | dr_line (double x1, double y1, double x2, double y2, const char *color) |
| Plot a line between [x1,y1] and [x2,y2] using color. More... | |
| void | dr_marker (double x, double y, int type, const char *color) |
| Place a marker to (x,y). Possible markers are: DR_MARKER_CIRCLE, DR_MARKER_TRIANGLE, DR_MARKER_CROSS. More... | |
| void | dr_text (double x, double y, int hz_al, int vr_al, const char *text, const char *color) |
| Place a text to (x,y). More... | |
| void | dr_text_pix (int px, int py, const char *text, const char *color) |
| Temporary code to output text to screen coordinates. More... | |
| void | dr_scale (double xmin, double ymin, double xmax, double ymax) |
| Scale the shown area. Prior rescaling, the area is normalized to keep the aspect ratio. More... | |
| void | dr_replot (void) |
| Redraw the screen content. More... | |
| void | dr_erase (void) |
| Clear the screen and erase the drawn objects from memory. More... | |
| void | dr_circle (double x, double y, double r, const char *color) |
| Plot a circle of radius r at [x,y] using color. More... | |
| void | dr_cov_ellipse (double x, double y, double c11, double c12, double c22, const char *color) |
| Plot a covariance ellipse to depict uncertainty. More... | |
| void | dr_zoom (void) |
| Interactive zooming until enter, space or 'q' is pressed. More... | |
| void | dr_fit (void) |
| Scale all drawn objects to fit the screen. More... | |
| void | dr_save (const char *filename) |
| Save the screen into a PNG image (needs extra packages). More... | |
| void | dr_equal (int equal) |
| Enable or disable equal drawing unit per pixel ratio for both axis. More... | |
| void | dr_print_database (void) |
| Debug function to print buffer. More... | |
Variables | |
| char * | dr_COLORS [] |
| int | dr_COLORS_CNT |
| void dr_circle | ( | double | x, |
| double | y, | ||
| double | r, | ||
| const char * | color | ||
| ) |
Plot a circle of radius r at [x,y] using color.
| x | X coordinate of the center of the circle. |
| y | Y coordinate of the center of the circle. |
| r | Radius of the circle. |
| color | The color of the circle as "red", "green",... see dr_COLORS. |
| void dr_close | ( | void | ) |
Close the drawing window.
| void dr_cov_ellipse | ( | double | x, |
| double | y, | ||
| double | cxx, | ||
| double | cxy, | ||
| double | cyy, | ||
| const char * | color | ||
| ) |
Plot a covariance ellipse to depict uncertainty.
The covariance ellipse is drawn by breaking it up into line segments.
Acknowledgement: the core equations are from Lindsay's kzoom.
| x | X coordinate of the mean of the distribution. |
| y | Y coordinate of the mean of the distribution. |
| cxx | The variance of the X coordinate. |
| cxy | The XY covariance. |
| cyy | The variance of the Y coordinate. |
| color | The color of the ellipse as "red", "green",... see dr_COLORS. |
| void dr_equal | ( | int | equal | ) |
Enable or disable equal drawing unit per pixel ratio for both axis.
| equal | 1 - enabled, 0 - disabled |
| void dr_erase | ( | void | ) |
Clear the screen and erase the drawn objects from memory.
| void dr_fit | ( | void | ) |
Scale all drawn objects to fit the screen.
| void dr_init | ( | int | screen_x_max, |
| int | screen_y_max, | ||
| double | xmin, | ||
| double | ymin, | ||
| double | xmax, | ||
| double | ymax | ||
| ) |
Initialize the drawing module.
| screen_y_max | [pixel] The height of the drawing screen in pixels. |
| screen_x_max | [pixel] The width of the drawing screen in pixels. |
| xmin | Minimum x coordinate of the drawing area in drawing units. |
| ymin | Minimum y coordinate of the drawing area in drawing units. |
| xmax | Maximum x coordinate of the drawing area in drawing units. |
| ymax | Maximum y coordinate of the drawing area in drawing units. |
| void dr_line | ( | double | x1, |
| double | y1, | ||
| double | x2, | ||
| double | y2, | ||
| const char * | color | ||
| ) |
Plot a line between [x1,y1] and [x2,y2] using color.
| x1 | x coordinate of the first point. |
| y1 | y coordinate of the first point. |
| x2 | x coordinate of the second point. |
| y2 | y coordinate of the second point. |
| color | The color of the line as "red", "green",... see dr_COLORS. |
| void dr_marker | ( | double | x, |
| double | y, | ||
| int | type, | ||
| const char * | color | ||
| ) |
Place a marker to (x,y). Possible markers are: DR_MARKER_CIRCLE, DR_MARKER_TRIANGLE, DR_MARKER_CROSS.
| x | X coordinate of the marker. |
| y | Y coordinate of the marker. |
| type | The type of the marker. One of DR_MARKER_CIRCLE, DR_MARKER_TRIANGLE, DR_MARKER_CROSS. |
| color | The color of the marker as "red", "green",... see dr_COLORS. |
| void dr_print_database | ( | void | ) |
Debug function to print buffer.
| void dr_replot | ( | void | ) |
Redraw the screen content.
| void dr_save | ( | const char * | filename | ) |
Save the screen into a PNG image (needs extra packages).
| filename | The name of the file under which the image is saved. |
| void dr_scale | ( | double | xmin, |
| double | ymin, | ||
| double | xmax, | ||
| double | ymax | ||
| ) |
Scale the shown area. Prior rescaling, the area is normalized to keep the aspect ratio.
| xmin | Minimum X coordinate of the shown area. |
| ymin | Minimum Y coordinate of the shown area. |
| xmax | Maximum X coordinate of the shown area. |
| ymax | Maximum X coordinate of the shown area. |
| void dr_text | ( | double | x, |
| double | y, | ||
| int | hz_al, | ||
| int | vr_al, | ||
| const char * | text, | ||
| const char * | color | ||
| ) |
Place a text to (x,y).
| x | X coordinate of the text. |
| y | Y coordinate of the text. |
| hz_al | Horizontal alignment. - CURRENTLY NOT USED. |
| vr_al | Horizontal alignment. - CURRENTLY NOT USED. |
| text | The text to be shown. |
| color | The color of the marker as "red", "green",... see dr_COLORS. |
| void dr_text_pix | ( | int | px, |
| int | py, | ||
| const char * | text, | ||
| const char * | color | ||
| ) |
Temporary code to output text to screen coordinates.
| px | [Pixel] X coordinate of the text. |
| py | [Pixel] Y coordinate of the text. |
| text | The text to be shown. |
| color | The color of the marker as "red", "green",... see dr_COLORS. |
| void dr_zoom | ( | void | ) |
Interactive zooming until enter, space or 'q' is pressed.
Use mouse or numeric keypad to pan/zoom. On the numeric keypad 9,3 will zoom in/out, 2,8 will move the drawing up/down, 4,6 will move left/right. Push r to redraw and c to reset to initial zoom level and view position.
When using the mouse, left click on figure top/bottom will move the drawing down/up, clicking on the left or right side of the figure will move the drawing right or left. Moving the wheel will zoom in and out.
| char* dr_COLORS[] |
| int dr_COLORS_CNT |


{% extends '_layouts/layout.html' %} {% block page_title %}{% endblock %} {% block body_css_classes %}nhsuk-frontend{% endblock %} {% block content %}
You should be contacted in XXXX. The call might show as ‘number withheld’ on your display.
During the call [this will happen]
NHS.UK has lots of information to help if you have symptoms.
You can find out:
You can also:


Names go here
See Our Github Repository DatasetAccess to electricity is important for promoting economic development along with improving living conditions. Around 1.2 billion people worldwide do not have electricity in their homes, many of them located in Africa and Asia. The first step in this process is to understand the location of existing energy infrastructure, which helps enable analysis of the distribution of energy resources as well as the consumption of energy. Doing this through surveys is incredibly time-consuming, which is why we are trying to locate energy infrastructure automatically by applying deep learning techniques to overhead imagery.
Using deep learning, we can feed an image to a model, and the model is able to make predictions about the contents or characteristics of that image. A common
technique for image analysis is classification, in which the model predicts the class of the image out of a list of possible classes.
In the image below, the model predicts that the image is of a cat, and is 90% confident with this classification. The model learns how to predict these classifications based
on examples that are shown to it. After it has been trained, it can classify images that it has not seen before.
For this project, we are focusing on object detection, which is a combination of classification with localization. The model analyzes images and predicts bounding boxes that
surround each object. It then also classifies each object, producing a confidence score corresponding to the prediction. In the image below, the model predicted that there was
an object in the box shown in red, and also predicted that the object within that box is a cat. The model learns how to predict these boxes and classifications based on examples shown to it.
These examples have labels that we refer to as ground truth that contain the information of where the objects are in the image.
For five years, the Duke Energy Data Analytics Lab has worked on developing deep learning models that identify energy infrastructure, with an end goal of generating maps of power grid networks that can aid policymakers in implementing effective electrification strategies. In 2015-16, researchers created a model that can detect solar photovoltaic arrays with high accuracy [2015-16 Bass Connections Team]. In 2018-19, this model was improved to identify different types of transmission and distribution energy infrastructures, including power lines and transmission towers [2018-19 Bass Connections Team]. Last year's project focused on increasing the adaptability of detection models across different geographies by creating realistic synthetic imagery [2019-20 Bass Connections Team]. In our project, we build upon this progress and try to improve the model's ability to detect rare objects.
Object detection networks, like the one used in this work, are notorious for their "data hunger," requiring large amounts of annotated training data to perform well. For common infrastructure like buildings and roads, there is ample real-world data available to train such models. However, for rare objects like wind turbines, there is not enough available imagery to satisfy the data requirements of these models. Further, due to their rarity and low spatial density in overhead imagery, acquiring more data can be very expensive.
Since training data is difficult to collect, in this project we explore creating synthetic data to supplement the real data that are available. We do this using CityEngine, which can render and generate 3D landscapes and structures based on input from the designer. In our case, we are populating a landscape with wind turbine models. Then we can position the camera in the overhead position and capture images with similar appearances to overhead imagery. Since we placed the wind turbines in the synthetic image, we can also generate ground truth labels for each of these images.
Here you can see our roadmap for the research project. In the following sections, we will discuss each of these steps.
 Images of wind turbines predominantly come from California, the Midwest, and around northern Texas.
From these images, we can notice significant variability in features like land types and even wind turbine
shapes between different states. For example, imagery from California is almost exclusively in
desert regions. California has a range of sizes of wind turbines including some that are small
and densely-clustered. On the other end of the spectrum, states like Maine have mostly large
wind turbines in regions with lots of vegetation. Images from the same state tend to be
relatively self-similar.
By including variation in features like geography, wind turbine size, and shadow size in the training dataset,
the model can generalize more broadly. However, it can be very difficult for the model to learn these novel
features if they are absent from the training data.
Ground truth labels were created using the image labeling GUI pyimannotate. Bounding boxes were hand-drawn around the wind turbines in each image, and the labels were stored in .txt files to be accessed during training and testing.
The size of the raw overhead images was very large and slowed training speeds. To increase efficiency, we divided the 1114x1114 pixel images into four 608x608 pixel patches that could then be fed into the model. Ground truth labels were then adjusted to account for resizing.
To create the synthetic data we used the program CityEngine, which can be used to generate landscapes and structures in a 3D environment. One reason why we picked CityEngine is that it uses a hyper-realistic graphics engine called the Unreal Engine. The program also allows the integration of python scripts along with the ability to take and save images with cameras, which is useful for automating the collection of our synthetic data.
To create the synthetic imagery, we first compiled a list of overhead images that did not contain wind turbines. These images were for the background on which to generate wind turbine models. We also collected 3D wind turbine models from online that we would like to use for the synthetic data.
We then used a python script and CityEngine files to randomly select the images and generate the 3D wind turbine models in random locations on top of the images. The script then moves the camera to the four quadrants of the images, and in each location, it captures and saves a photo. This process is then repeated with the wind turbine models colored in as black and the background colored as white. These black and white images tell us where the models are placed and can be used to create ground truth labels.
After this process, we have a set of synthetic images, and for each of these images, we have a corresponding file that locates the position of the wind turbine models within the image.
The last step is to then use the black and white annotations to create ground truth labels. This is done by finding groups of black pixels and then recording the dimensions and positions of these pixel groupings. This can be visualized as drawing boxes around each of these models. This is done for each image, giving us a label corresponding with each image, where the label contains the information about every model within that image.
Once we have our synthetic data created and our real imagery preprocessed, we are ready to run experiments. These experiments involve altering the composition of the training dataset to see how the performance of the model changes. The basic experimental setup for this project is to train the model on a control condition with just real data, and then to use the same dataset but supplement it with synthetic images, and then measure the difference in performance. This will produce two different models and their performance is measured on the same testing set. With this setup, we are only changing one variable and so we can attribute any differences in performance to the added synthetic data.
To understand our results, it's important that we first understand the metrics that we have chosen to measure performance. The primary metrics we look at are precision and recall. We'll explain how these metrics can be interpreted in terms of the images on the left.
Since the goal of this model is to detect objects in very large sets of overhead imagery, manually removing objects misclassified as wind turbines is much easier than identifying undetected wind turbines across the entire dataset. For this reason, we prioritize recall over precision as a metric of good performance.
Adding synthetic data to our training set significantly improved the precision of our model. However, the recall does not change significantly. Our hypothesis for this is that with the added synthetic data, model was doing well on large wind turbines while missing many of the small wind turbines. This prompted us to create synthetic data that contained small wind turbines to try to fix this issue.
In addition to this first experiment, we also conducted additional experiments by changing how the dataset was split between the training and testing. One experiment that we explored was excluding a geographic region from the testing set. We wanted to choose a region that would be the most difficult for the model to perform on without having training data to learn from. We chose to exclude California and Arizona from the testing set because the geography is both self-similar and fairly different from the other regions and also because the small wind turbines in California would be very difficult for the model to test on. In this case, our training set contains no small wind turbines while the testing set does contain small turbines.
After testing the model with this setup, we then were able to add synthetic data to see if the performance improves. We specifically created synthetic data that mimicked the real overhead imagery in California and Arizona. In order to do this, we made a histogram of the sizes of the wind turbines located in CA and AZ and tried to match that size distribution in our synthetic data. We then added these to the training dataset and observed how the performance changed.
After adding synthetic data, the precision decreases a significant amount while the recall improves very slightly. This indicates that we need to improve the quality of our synthetic data to better replicate the real world overhead images from California and Arizona. This could include purchasing a more realistic model for our small wind turbines or increasing the variety of synthetic data by randomizing lighting conditions.
The goal of this project was to create synthetic data that could be added to our training set to improve performance. This goal was met, but we think that with the fine-tuning of our synthetic data, we should be able to increase the performance more, especially in terms of the recall. For our additional experiment of testing on novel geographies and turbines, the results indicate that the synthetic data we made to mimic the real overhead imagery in California and Arizona needs to be improved in terms of its quality, especially the model for the small wind turbine.
Dr. Kyle Bradbury
Dr. Jordan Malof


rotten > Library > Biographies > Presidents > Abraham Lincoln
Abraham Lincoln
While he may not have been gay, Lincoln did share a double bed with an attractive younger man, Joshua Fry Speed, for four years. Certain homosexual writers state outright that Lincoln was bisexual, but there is no actual evidence to this effect other than assumed innuendo and wishful thinking. And the men gave each other advice with regards to their women problems.
Lincoln's eldest son, Robert Todd Lincoln, was bad luck for U.S. Presidents, being present at three U.S. Presidential assassinations -- Lincoln's, Garfield's and McKinley's. To be technical, Robert was not actually present at the last one, but instead had just arrived in town. Even so, for the good of the country, he avoided chief executives altogether after McKinley.
Lincoln's corpse has led an interesting life. The lead-lined presidential coffin has been moved 17 times, and exhumed and examined no fewer than five times. One attempt was made to rob the body and hold it for ransom, but the police were waiting. To avoid future threats of grave robbery, Lincoln was buried in a cage under two tons of concrete. It seems to have worked; Lincoln hasn't been seen since.
Scholarly consensus has Lincoln as America's greatest President. But no man this... homely.... would ever be elected now, in these days of TV, ADD, and soundbytes. Lieberman or Kerry? Holy christ you have got to be kidding.
Timeline
| 12 Feb 1809 |
Abraham Lincoln born, Hardin County KY, in a log cabin without floors, doors, or windows. |
| 1836 |
Proposes marriage to Mary Owens. She declines. |
| 9 Sep 1836 |
Receives license to practice law. |
| 15 Apr 1837 |
Lincoln meets and immediately moves in with Joshua Fry Speed, an attactive and intelligent young man, and they share a double bed together for the next four years. |
| 15 Feb 1842 |
Joshua Speed marries Fanny Hennings. |
| 4 Nov 1842 |
Abraham Lincoln marries Mary Todd. |
| 1 Aug 1843 |
Son, Robert Todd Lincoln, born. |
| 10 Mar 1846 |
Son, Edward Baker Lincoln, born. |
| 1 Feb 1850 |
Edward Baker Lincoln dies. |
| 21 Dec 1850 |
Son, William Wallace Lincoln, born. |
| 4 Apr 1853 |
Son, Thomas (Tad) Lincoln, born. |
| 4 Mar 1861 |
Abraham Lincoln inaugurated as 16th President. |
| 1 Jan 1863 |
Emancipation Proclamation. |
| 14 Apr 1865 |
Robert Todd Lincoln arrives in Washington DC, in time for his father's assassination. |
| 14 Apr 1865 |
Abraham Lincoln assassinated by John Wilkes Booth, at Ford's Theater in Washington, DC. |
| 15 Apr 1865 |
Abraham Lincoln dies at 7:22 am. |
| 26 Apr 1865 |
John Wilkes Booth killed. |
| 4 May 1865 |
Buried at Oak Ridge Cemetery, Springfield IL. |
| 21 Dec 1865 |
Lincoln's coffin opened. |
| 19 Sep 1871 |
Lincoln's coffin opened. |
| 9 Oct 1874 |
Lincoln's coffin opened. |
| 7 Nov 1876 |
An attempt is made to steal Lincoln's corpse, and hold it for ransom. |
| 22 Jun 1877 |
Lincoln's would-be tomb robbers begin serving prison sentence. |
| 2 Jul 1881 |
Robert Todd Lincoln arrives at a train depot in Washington DC, barely in time to catch President Garfield's assassination by James Guiteau. |
| 29 May 1882 |
Joshua Speed dies, Louisville KY. |
| 14 Apr 1887 |
Lincoln's coffin opened. |
| 6 Sep 1901 |
Robert Todd Lincoln arrives in Buffalo NY, in time for McKinley's assassination. |
| 26 Sep 1901 |
Abraham Lincoln's body is exhumed an examined. The corpse is recognizably Lincoln, with the exception that the eyebrows have fallen out. Twenty-three individuals examine Lincoln, all agreeing that it is indeed him. Lincoln is then reburied for the last time, under two tons of cement. |
| 1909 |
Lincoln's face put on the penny. |
| 1 Feb 1963 |
The last man to see Lincoln's corpse as it was exhumed in 1901, Fleetwood Lindley, dies. Fleetwood was 13 when he saw Lincoln; before dying, he stated, "Yes, his face was chalky white. His clothes were mildewed. And I was allowed to hold one of the leather straps as we lowered the casket for the concrete to be poured. I was not scared at the time but I slept with Lincoln for the next six months." |
Pornopolis |
Rotten |
Faces of Death |
Famous Nudes
|


# -*- coding: utf-8 -*- # # Copyright (C) 2012-2017 The Python Software Foundation. # See LICENSE.txt and CONTRIBUTORS.txt. # """PEP 376 implementation.""" from __future__ import unicode_literals import base64 import codecs import contextlib import hashlib import logging import os import posixpath import sys import zipimport from . import DistlibException, resources from .compat import StringIO from .version import get_scheme, UnsupportedVersionError from .metadata import (Metadata, METADATA_FILENAME, WHEEL_METADATA_FILENAME, LEGACY_METADATA_FILENAME) from .util import (parse_requirement, cached_property, parse_name_and_version, read_exports, write_exports, CSVReader, CSVWriter) __all__ = ['Distribution', 'BaseInstalledDistribution', 'InstalledDistribution', 'EggInfoDistribution', 'DistributionPath'] logger = logging.getLogger(__name__) EXPORTS_FILENAME = 'pydist-exports.json' COMMANDS_FILENAME = 'pydist-commands.json' DIST_FILES = ('INSTALLER', METADATA_FILENAME, 'RECORD', 'REQUESTED', 'RESOURCES', EXPORTS_FILENAME, 'SHARED') DISTINFO_EXT = '.dist-info' class _Cache(object): """ A simple cache mapping names and .dist-info paths to distributions """ def __init__(self): """ Initialise an instance. There is normally one for each DistributionPath. """ self.name = {} self.path = {} self.generated = False def clear(self): """ Clear the cache, setting it to its initial state. """ self.name.clear() self.path.clear() self.generated = False def add(self, dist): """ Add a distribution to the cache. :param dist: The distribution to add. """ if dist.path not in self.path: self.path[dist.path] = dist self.name.setdefault(dist.key, []).append(dist) class DistributionPath(object): """ Represents a set of distributions installed on a path (typically sys.path). """ def __init__(self, path=None, include_egg=False): """ Create an instance from a path, optionally including legacy (distutils/ setuptools/distribute) distributions. :param path: The path to use, as a list of directories. If not specified, sys.path is used. :param include_egg: If True, this instance will look for and return legacy distributions as well as those based on PEP 376. """ if path is None: path = sys.path self.path = path self._include_dist = True self._include_egg = include_egg self._cache = _Cache() self._cache_egg = _Cache() self._cache_enabled = True self._scheme = get_scheme('default') def _get_cache_enabled(self): return self._cache_enabled def _set_cache_enabled(self, value): self._cache_enabled = value cache_enabled = property(_get_cache_enabled, _set_cache_enabled) def clear_cache(self): """ Clears the internal cache. """ self._cache.clear() self._cache_egg.clear() def _yield_distributions(self): """ Yield .dist-info and/or .egg(-info) distributions. """ # We need to check if we've seen some resources already, because on # some Linux systems (e.g. some Debian/Ubuntu variants) there are # symlinks which alias other files in the environment. seen = set() for path in self.path: finder = resources.finder_for_path(path) if finder is None: continue r = finder.find('') if not r or not r.is_container: continue rset = sorted(r.resources) for entry in rset: r = finder.find(entry) if not r or r.path in seen: continue if self._include_dist and entry.endswith(DISTINFO_EXT): possible_filenames = [METADATA_FILENAME, WHEEL_METADATA_FILENAME, LEGACY_METADATA_FILENAME] for metadata_filename in possible_filenames: metadata_path = posixpath.join(entry, metadata_filename) pydist = finder.find(metadata_path) if pydist: break else: continue with contextlib.closing(pydist.as_stream()) as stream: metadata = Metadata(fileobj=stream, scheme='legacy') logger.debug('Found %s', r.path) seen.add(r.path) yield new_dist_class(r.path, metadata=metadata, env=self) elif self._include_egg and entry.endswith(('.egg-info', '.egg')): logger.debug('Found %s', r.path) seen.add(r.path) yield old_dist_class(r.path, self) def _generate_cache(self): """ Scan the path for distributions and populate the cache with those that are found. """ gen_dist = not self._cache.generated gen_egg = self._include_egg and not self._cache_egg.generated if gen_dist or gen_egg: for dist in self._yield_distributions(): if isinstance(dist, InstalledDistribution): self._cache.add(dist) else: self._cache_egg.add(dist) if gen_dist: self._cache.generated = True if gen_egg: self._cache_egg.generated = True @classmethod def distinfo_dirname(cls, name, version): """ The *name* and *version* parameters are converted into their filename-escaped form, i.e. any ``'-'`` characters are replaced with ``'_'`` other than the one in ``'dist-info'`` and the one separating the name from the version number. :parameter name: is converted to a standard distribution name by replacing any runs of non- alphanumeric characters with a single ``'-'``. :type name: string :parameter version: is converted to a standard version string. Spaces become dots, and all other non-alphanumeric characters (except dots) become dashes, with runs of multiple dashes condensed to a single dash. :type version: string :returns: directory name :rtype: string""" name = name.replace('-', '_') return '-'.join([name, version]) + DISTINFO_EXT def get_distributions(self): """ Provides an iterator that looks for distributions and returns :class:`InstalledDistribution` or :class:`EggInfoDistribution` instances for each one of them. :rtype: iterator of :class:`InstalledDistribution` and :class:`EggInfoDistribution` instances """ if not self._cache_enabled: for dist in self._yield_distributions(): yield dist else: self._generate_cache() for dist in self._cache.path.values(): yield dist if self._include_egg: for dist in self._cache_egg.path.values(): yield dist def get_distribution(self, name): """ Looks for a named distribution on the path. This function only returns the first result found, as no more than one value is expected. If nothing is found, ``None`` is returned. :rtype: :class:`InstalledDistribution`, :class:`EggInfoDistribution` or ``None`` """ result = None name = name.lower() if not self._cache_enabled: for dist in self._yield_distributions(): if dist.key == name: result = dist break else: self._generate_cache() if name in self._cache.name: result = self._cache.name[name][0] elif self._include_egg and name in self._cache_egg.name: result = self._cache_egg.name[name][0] return result def provides_distribution(self, name, version=None): """ Iterates over all distributions to find which distributions provide *name*. If a *version* is provided, it will be used to filter the results. This function only returns the first result found, since no more than one values are expected. If the directory is not found, returns ``None``. :parameter version: a version specifier that indicates the version required, conforming to the format in ``PEP-345`` :type name: string :type version: string """ matcher = None if version is not None: try: matcher = self._scheme.matcher('%s (%s)' % (name, version)) except ValueError: raise DistlibException('invalid name or version: %r, %r' % (name, version)) for dist in self.get_distributions(): # We hit a problem on Travis where enum34 was installed and doesn't # have a provides attribute ... if not hasattr(dist, 'provides'): logger.debug('No "provides": %s', dist) else: provided = dist.provides for p in provided: p_name, p_ver = parse_name_and_version(p) if matcher is None: if p_name == name: yield dist break else: if p_name == name and matcher.match(p_ver): yield dist break def get_file_path(self, name, relative_path): """ Return the path to a resource file. """ dist = self.get_distribution(name) if dist is None: raise LookupError('no distribution named %r found' % name) return dist.get_resource_path(relative_path) def get_exported_entries(self, category, name=None): """ Return all of the exported entries in a particular category. :param category: The category to search for entries. :param name: If specified, only entries with that name are returned. """ for dist in self.get_distributions(): r = dist.exports if category in r: d = r[category] if name is not None: if name in d: yield d[name] else: for v in d.values(): yield v class Distribution(object): """ A base class for distributions, whether installed or from indexes. Either way, it must have some metadata, so that's all that's needed for construction. """ build_time_dependency = False """ Set to True if it's known to be only a build-time dependency (i.e. not needed after installation). """ requested = False """A boolean that indicates whether the ``REQUESTED`` metadata file is present (in other words, whether the package was installed by user request or it was installed as a dependency).""" def __init__(self, metadata): """ Initialise an instance. :param metadata: The instance of :class:`Metadata` describing this distribution. """ self.metadata = metadata self.name = metadata.name self.key = self.name.lower() # for case-insensitive comparisons self.version = metadata.version self.locator = None self.digest = None self.extras = None # additional features requested self.context = None # environment marker overrides self.download_urls = set() self.digests = {} @property def source_url(self): """ The source archive download URL for this distribution. """ return self.metadata.source_url download_url = source_url # Backward compatibility @property def name_and_version(self): """ A utility property which displays the name and version in parentheses. """ return '%s (%s)' % (self.name, self.version) @property def provides(self): """ A set of distribution names and versions provided by this distribution. :return: A set of "name (version)" strings. """ plist = self.metadata.provides s = '%s (%s)' % (self.name, self.version) if s not in plist: plist.append(s) return plist def _get_requirements(self, req_attr): md = self.metadata logger.debug('Getting requirements from metadata %r', md.todict()) reqts = getattr(md, req_attr) return set(md.get_requirements(reqts, extras=self.extras, env=self.context)) @property def run_requires(self): return self._get_requirements('run_requires') @property def meta_requires(self): return self._get_requirements('meta_requires') @property def build_requires(self): return self._get_requirements('build_requires') @property def test_requires(self): return self._get_requirements('test_requires') @property def dev_requires(self): return self._get_requirements('dev_requires') def matches_requirement(self, req): """ Say if this instance matches (fulfills) a requirement. :param req: The requirement to match. :rtype req: str :return: True if it matches, else False. """ # Requirement may contain extras - parse to lose those # from what's passed to the matcher r = parse_requirement(req) scheme = get_scheme(self.metadata.scheme) try: matcher = scheme.matcher(r.requirement) except UnsupportedVersionError: # XXX compat-mode if cannot read the version logger.warning('could not read version %r - using name only', req) name = req.split()[0] matcher = scheme.matcher(name) name = matcher.key # case-insensitive result = False for p in self.provides: p_name, p_ver = parse_name_and_version(p) if p_name != name: continue try: result = matcher.match(p_ver) break except UnsupportedVersionError: pass return result def __repr__(self): """ Return a textual representation of this instance, """ if self.source_url: suffix = ' [%s]' % self.source_url else: suffix = '' return '<Distribution %s (%s)%s>' % (self.name, self.version, suffix) def __eq__(self, other): """ See if this distribution is the same as another. :param other: The distribution to compare with. To be equal to one another. distributions must have the same type, name, version and source_url. :return: True if it is the same, else False. """ if type(other) is not type(self): result = False else: result = (self.name == other.name and self.version == other.version and self.source_url == other.source_url) return result def __hash__(self): """ Compute hash in a way which matches the equality test. """ return hash(self.name) + hash(self.version) + hash(self.source_url) class BaseInstalledDistribution(Distribution): """ This is the base class for installed distributions (whether PEP 376 or legacy). """ hasher = None def __init__(self, metadata, path, env=None): """ Initialise an instance. :param metadata: An instance of :class:`Metadata` which describes the distribution. This will normally have been initialised from a metadata file in the ``path``. :param path: The path of the ``.dist-info`` or ``.egg-info`` directory for the distribution. :param env: This is normally the :class:`DistributionPath` instance where this distribution was found. """ super(BaseInstalledDistribution, self).__init__(metadata) self.path = path self.dist_path = env def get_hash(self, data, hasher=None): """ Get the hash of some data, using a particular hash algorithm, if specified. :param data: The data to be hashed. :type data: bytes :param hasher: The name of a hash implementation, supported by hashlib, or ``None``. Examples of valid values are ``'sha1'``, ``'sha224'``, ``'sha384'``, '``sha256'``, ``'md5'`` and ``'sha512'``. If no hasher is specified, the ``hasher`` attribute of the :class:`InstalledDistribution` instance is used. If the hasher is determined to be ``None``, MD5 is used as the hashing algorithm. :returns: The hash of the data. If a hasher was explicitly specified, the returned hash will be prefixed with the specified hasher followed by '='. :rtype: str """ if hasher is None: hasher = self.hasher if hasher is None: hasher = hashlib.md5 prefix = '' else: hasher = getattr(hashlib, hasher) prefix = '%s=' % self.hasher digest = hasher(data).digest() digest = base64.urlsafe_b64encode(digest).rstrip(b'=').decode('ascii') return '%s%s' % (prefix, digest) class InstalledDistribution(BaseInstalledDistribution): """ Created with the *path* of the ``.dist-info`` directory provided to the constructor. It reads the metadata contained in ``pydist.json`` when it is instantiated., or uses a passed in Metadata instance (useful for when dry-run mode is being used). """ hasher = 'sha256' def __init__(self, path, metadata=None, env=None): self.modules = [] self.finder = finder = resources.finder_for_path(path) if finder is None: raise ValueError('finder unavailable for %s' % path) if env and env._cache_enabled and path in env._cache.path: metadata = env._cache.path[path].metadata elif metadata is None: r = finder.find(METADATA_FILENAME) # Temporary - for Wheel 0.23 support if r is None: r = finder.find(WHEEL_METADATA_FILENAME) # Temporary - for legacy support if r is None: r = finder.find('METADATA') if r is None: raise ValueError('no %s found in %s' % (METADATA_FILENAME, path)) with contextlib.closing(r.as_stream()) as stream: metadata = Metadata(fileobj=stream, scheme='legacy') super(InstalledDistribution, self).__init__(metadata, path, env) if env and env._cache_enabled: env._cache.add(self) r = finder.find('REQUESTED') self.requested = r is not None p = os.path.join(path, 'top_level.txt') if os.path.exists(p): with open(p, 'rb') as f: data = f.read().decode('utf-8') self.modules = data.splitlines() def __repr__(self): return '<InstalledDistribution %r %s at %r>' % ( self.name, self.version, self.path) def __str__(self): return "%s %s" % (self.name, self.version) def _get_records(self): """ Get the list of installed files for the distribution :return: A list of tuples of path, hash and size. Note that hash and size might be ``None`` for some entries. The path is exactly as stored in the file (which is as in PEP 376). """ results = [] r = self.get_distinfo_resource('RECORD') with contextlib.closing(r.as_stream()) as stream: with CSVReader(stream=stream) as record_reader: # Base location is parent dir of .dist-info dir #base_location = os.path.dirname(self.path) #base_location = os.path.abspath(base_location) for row in record_reader: missing = [None for i in range(len(row), 3)] path, checksum, size = row + missing #if not os.path.isabs(path): # path = path.replace('/', os.sep) # path = os.path.join(base_location, path) results.append((path, checksum, size)) return results @cached_property def exports(self): """ Return the information exported by this distribution. :return: A dictionary of exports, mapping an export category to a dict of :class:`ExportEntry` instances describing the individual export entries, and keyed by name. """ result = {} r = self.get_distinfo_resource(EXPORTS_FILENAME) if r: result = self.read_exports() return result def read_exports(self): """ Read exports data from a file in .ini format. :return: A dictionary of exports, mapping an export category to a list of :class:`ExportEntry` instances describing the individual export entries. """ result = {} r = self.get_distinfo_resource(EXPORTS_FILENAME) if r: with contextlib.closing(r.as_stream()) as stream: result = read_exports(stream) return result def write_exports(self, exports): """ Write a dictionary of exports to a file in .ini format. :param exports: A dictionary of exports, mapping an export category to a list of :class:`ExportEntry` instances describing the individual export entries. """ rf = self.get_distinfo_file(EXPORTS_FILENAME) with open(rf, 'w') as f: write_exports(exports, f) def get_resource_path(self, relative_path): """ NOTE: This API may change in the future. Return the absolute path to a resource file with the given relative path. :param relative_path: The path, relative to .dist-info, of the resource of interest. :return: The absolute path where the resource is to be found. """ r = self.get_distinfo_resource('RESOURCES') with contextlib.closing(r.as_stream()) as stream: with CSVReader(stream=stream) as resources_reader: for relative, destination in resources_reader: if relative == relative_path: return destination raise KeyError('no resource file with relative path %r ' 'is installed' % relative_path) def list_installed_files(self): """ Iterates over the ``RECORD`` entries and returns a tuple ``(path, hash, size)`` for each line. :returns: iterator of (path, hash, size) """ for result in self._get_records(): yield result def write_installed_files(self, paths, prefix, dry_run=False): """ Writes the ``RECORD`` file, using the ``paths`` iterable passed in. Any existing ``RECORD`` file is silently overwritten. prefix is used to determine when to write absolute paths. """ prefix = os.path.join(prefix, '') base = os.path.dirname(self.path) base_under_prefix = base.startswith(prefix) base = os.path.join(base, '') record_path = self.get_distinfo_file('RECORD') logger.info('creating %s', record_path) if dry_run: return None with CSVWriter(record_path) as writer: for path in paths: if os.path.isdir(path) or path.endswith(('.pyc', '.pyo')): # do not put size and hash, as in PEP-376 hash_value = size = '' else: size = '%d' % os.path.getsize(path) with open(path, 'rb') as fp: hash_value = self.get_hash(fp.read()) if path.startswith(base) or (base_under_prefix and path.startswith(prefix)): path = os.path.relpath(path, base) writer.writerow((path, hash_value, size)) # add the RECORD file itself if record_path.startswith(base): record_path = os.path.relpath(record_path, base) writer.writerow((record_path, '', '')) return record_path def check_installed_files(self): """ Checks that the hashes and sizes of the files in ``RECORD`` are matched by the files themselves. Returns a (possibly empty) list of mismatches. Each entry in the mismatch list will be a tuple consisting of the path, 'exists', 'size' or 'hash' according to what didn't match (existence is checked first, then size, then hash), the expected value and the actual value. """ mismatches = [] base = os.path.dirname(self.path) record_path = self.get_distinfo_file('RECORD') for path, hash_value, size in self.list_installed_files(): if not os.path.isabs(path): path = os.path.join(base, path) if path == record_path: continue if not os.path.exists(path): mismatches.append((path, 'exists', True, False)) elif os.path.isfile(path): actual_size = str(os.path.getsize(path)) if size and actual_size != size: mismatches.append((path, 'size', size, actual_size)) elif hash_value: if '=' in hash_value: hasher = hash_value.split('=', 1)[0] else: hasher = None with open(path, 'rb') as f: actual_hash = self.get_hash(f.read(), hasher) if actual_hash != hash_value: mismatches.append((path, 'hash', hash_value, actual_hash)) return mismatches @cached_property def shared_locations(self): """ A dictionary of shared locations whose keys are in the set 'prefix', 'purelib', 'platlib', 'scripts', 'headers', 'data' and 'namespace'. The corresponding value is the absolute path of that category for this distribution, and takes into account any paths selected by the user at installation time (e.g. via command-line arguments). In the case of the 'namespace' key, this would be a list of absolute paths for the roots of namespace packages in this distribution. The first time this property is accessed, the relevant information is read from the SHARED file in the .dist-info directory. """ result = {} shared_path = os.path.join(self.path, 'SHARED') if os.path.isfile(shared_path): with codecs.open(shared_path, 'r', encoding='utf-8') as f: lines = f.read().splitlines() for line in lines: key, value = line.split('=', 1) if key == 'namespace': result.setdefault(key, []).append(value) else: result[key] = value return result def write_shared_locations(self, paths, dry_run=False): """ Write shared location information to the SHARED file in .dist-info. :param paths: A dictionary as described in the documentation for :meth:`shared_locations`. :param dry_run: If True, the action is logged but no file is actually written. :return: The path of the file written to. """ shared_path = os.path.join(self.path, 'SHARED') logger.info('creating %s', shared_path) if dry_run: return None lines = [] for key in ('prefix', 'lib', 'headers', 'scripts', 'data'): path = paths[key] if os.path.isdir(paths[key]): lines.append('%s=%s' % (key, path)) for ns in paths.get('namespace', ()): lines.append('namespace=%s' % ns) with codecs.open(shared_path, 'w', encoding='utf-8') as f: f.write('\n'.join(lines)) return shared_path def get_distinfo_resource(self, path): if path not in DIST_FILES: raise DistlibException('invalid path for a dist-info file: ' '%r at %r' % (path, self.path)) finder = resources.finder_for_path(self.path) if finder is None: raise DistlibException('Unable to get a finder for %s' % self.path) return finder.find(path) def get_distinfo_file(self, path): """ Returns a path located under the ``.dist-info`` directory. Returns a string representing the path. :parameter path: a ``'/'``-separated path relative to the ``.dist-info`` directory or an absolute path; If *path* is an absolute path and doesn't start with the ``.dist-info`` directory path, a :class:`DistlibException` is raised :type path: str :rtype: str """ # Check if it is an absolute path # XXX use relpath, add tests if path.find(os.sep) >= 0: # it's an absolute path? distinfo_dirname, path = path.split(os.sep)[-2:] if distinfo_dirname != self.path.split(os.sep)[-1]: raise DistlibException( 'dist-info file %r does not belong to the %r %s ' 'distribution' % (path, self.name, self.version)) # The file must be relative if path not in DIST_FILES: raise DistlibException('invalid path for a dist-info file: ' '%r at %r' % (path, self.path)) return os.path.join(self.path, path) def list_distinfo_files(self): """ Iterates over the ``RECORD`` entries and returns paths for each line if the path is pointing to a file located in the ``.dist-info`` directory or one of its subdirectories. :returns: iterator of paths """ base = os.path.dirname(self.path) for path, checksum, size in self._get_records(): # XXX add separator or use real relpath algo if not os.path.isabs(path): path = os.path.join(base, path) if path.startswith(self.path): yield path def __eq__(self, other): return (isinstance(other, InstalledDistribution) and self.path == other.path) # See http://docs.python.org/reference/datamodel#object.__hash__ __hash__ = object.__hash__ class EggInfoDistribution(BaseInstalledDistribution): """Created with the *path* of the ``.egg-info`` directory or file provided to the constructor. It reads the metadata contained in the file itself, or if the given path happens to be a directory, the metadata is read from the file ``PKG-INFO`` under that directory.""" requested = True # as we have no way of knowing, assume it was shared_locations = {} def __init__(self, path, env=None): def set_name_and_version(s, n, v): s.name = n s.key = n.lower() # for case-insensitive comparisons s.version = v self.path = path self.dist_path = env if env and env._cache_enabled and path in env._cache_egg.path: metadata = env._cache_egg.path[path].metadata set_name_and_version(self, metadata.name, metadata.version) else: metadata = self._get_metadata(path) # Need to be set before caching set_name_and_version(self, metadata.name, metadata.version) if env and env._cache_enabled: env._cache_egg.add(self) super(EggInfoDistribution, self).__init__(metadata, path, env) def _get_metadata(self, path): requires = None def parse_requires_data(data): """Create a list of dependencies from a requires.txt file. *data*: the contents of a setuptools-produced requires.txt file. """ reqs = [] lines = data.splitlines() for line in lines: line = line.strip() if line.startswith('['): logger.warning('Unexpected line: quitting requirement scan: %r', line) break r = parse_requirement(line) if not r: logger.warning('Not recognised as a requirement: %r', line) continue if r.extras: logger.warning('extra requirements in requires.txt are ' 'not supported') if not r.constraints: reqs.append(r.name) else: cons = ', '.join('%s%s' % c for c in r.constraints) reqs.append('%s (%s)' % (r.name, cons)) return reqs def parse_requires_path(req_path): """Create a list of dependencies from a requires.txt file. *req_path*: the path to a setuptools-produced requires.txt file. """ reqs = [] try: with codecs.open(req_path, 'r', 'utf-8') as fp: reqs = parse_requires_data(fp.read()) except IOError: pass return reqs tl_path = tl_data = None if path.endswith('.egg'): if os.path.isdir(path): p = os.path.join(path, 'EGG-INFO') meta_path = os.path.join(p, 'PKG-INFO') metadata = Metadata(path=meta_path, scheme='legacy') req_path = os.path.join(p, 'requires.txt') tl_path = os.path.join(p, 'top_level.txt') requires = parse_requires_path(req_path) else: # FIXME handle the case where zipfile is not available zipf = zipimport.zipimporter(path) fileobj = StringIO( zipf.get_data('EGG-INFO/PKG-INFO').decode('utf8')) metadata = Metadata(fileobj=fileobj, scheme='legacy') try: data = zipf.get_data('EGG-INFO/requires.txt') tl_data = zipf.get_data('EGG-INFO/top_level.txt').decode('utf-8') requires = parse_requires_data(data.decode('utf-8')) except IOError: requires = None elif path.endswith('.egg-info'): if os.path.isdir(path): req_path = os.path.join(path, 'requires.txt') requires = parse_requires_path(req_path) path = os.path.join(path, 'PKG-INFO') tl_path = os.path.join(path, 'top_level.txt') metadata = Metadata(path=path, scheme='legacy') else: raise DistlibException('path must end with .egg-info or .egg, ' 'got %r' % path) if requires: metadata.add_requirements(requires) # look for top-level modules in top_level.txt, if present if tl_data is None: if tl_path is not None and os.path.exists(tl_path): with open(tl_path, 'rb') as f: tl_data = f.read().decode('utf-8') if not tl_data: tl_data = [] else: tl_data = tl_data.splitlines() self.modules = tl_data return metadata def __repr__(self): return '<EggInfoDistribution %r %s at %r>' % ( self.name, self.version, self.path) def __str__(self): return "%s %s" % (self.name, self.version) def check_installed_files(self): """ Checks that the hashes and sizes of the files in ``RECORD`` are matched by the files themselves. Returns a (possibly empty) list of mismatches. Each entry in the mismatch list will be a tuple consisting of the path, 'exists', 'size' or 'hash' according to what didn't match (existence is checked first, then size, then hash), the expected value and the actual value. """ mismatches = [] record_path = os.path.join(self.path, 'installed-files.txt') if os.path.exists(record_path): for path, _, _ in self.list_installed_files(): if path == record_path: continue if not os.path.exists(path): mismatches.append((path, 'exists', True, False)) return mismatches def list_installed_files(self): """ Iterates over the ``installed-files.txt`` entries and returns a tuple ``(path, hash, size)`` for each line. :returns: a list of (path, hash, size) """ def _md5(path): f = open(path, 'rb') try: content = f.read() finally: f.close() return hashlib.md5(content).hexdigest() def _size(path): return os.stat(path).st_size record_path = os.path.join(self.path, 'installed-files.txt') result = [] if os.path.exists(record_path): with codecs.open(record_path, 'r', encoding='utf-8') as f: for line in f: line = line.strip() p = os.path.normpath(os.path.join(self.path, line)) # "./" is present as a marker between installed files # and installation metadata files if not os.path.exists(p): logger.warning('Non-existent file: %s', p) if p.endswith(('.pyc', '.pyo')): continue #otherwise fall through and fail if not os.path.isdir(p): result.append((p, _md5(p), _size(p))) result.append((record_path, None, None)) return result def list_distinfo_files(self, absolute=False): """ Iterates over the ``installed-files.txt`` entries and returns paths for each line if the path is pointing to a file located in the ``.egg-info`` directory or one of its subdirectories. :parameter absolute: If *absolute* is ``True``, each returned path is transformed into a local absolute path. Otherwise the raw value from ``installed-files.txt`` is returned. :type absolute: boolean :returns: iterator of paths """ record_path = os.path.join(self.path, 'installed-files.txt') if os.path.exists(record_path): skip = True with codecs.open(record_path, 'r', encoding='utf-8') as f: for line in f: line = line.strip() if line == './': skip = False continue if not skip: p = os.path.normpath(os.path.join(self.path, line)) if p.startswith(self.path): if absolute: yield p else: yield line def __eq__(self, other): return (isinstance(other, EggInfoDistribution) and self.path == other.path) # See http://docs.python.org/reference/datamodel#object.__hash__ __hash__ = object.__hash__ new_dist_class = InstalledDistribution old_dist_class = EggInfoDistribution class DependencyGraph(object): """ Represents a dependency graph between distributions. The dependency relationships are stored in an ``adjacency_list`` that maps distributions to a list of ``(other, label)`` tuples where ``other`` is a distribution and the edge is labeled with ``label`` (i.e. the version specifier, if such was provided). Also, for more efficient traversal, for every distribution ``x``, a list of predecessors is kept in ``reverse_list[x]``. An edge from distribution ``a`` to distribution ``b`` means that ``a`` depends on ``b``. If any missing dependencies are found, they are stored in ``missing``, which is a dictionary that maps distributions to a list of requirements that were not provided by any other distributions. """ def __init__(self): self.adjacency_list = {} self.reverse_list = {} self.missing = {} def add_distribution(self, distribution): """Add the *distribution* to the graph. :type distribution: :class:`distutils2.database.InstalledDistribution` or :class:`distutils2.database.EggInfoDistribution` """ self.adjacency_list[distribution] = [] self.reverse_list[distribution] = [] #self.missing[distribution] = [] def add_edge(self, x, y, label=None): """Add an edge from distribution *x* to distribution *y* with the given *label*. :type x: :class:`distutils2.database.InstalledDistribution` or :class:`distutils2.database.EggInfoDistribution` :type y: :class:`distutils2.database.InstalledDistribution` or :class:`distutils2.database.EggInfoDistribution` :type label: ``str`` or ``None`` """ self.adjacency_list[x].append((y, label)) # multiple edges are allowed, so be careful if x not in self.reverse_list[y]: self.reverse_list[y].append(x) def add_missing(self, distribution, requirement): """ Add a missing *requirement* for the given *distribution*. :type distribution: :class:`distutils2.database.InstalledDistribution` or :class:`distutils2.database.EggInfoDistribution` :type requirement: ``str`` """ logger.debug('%s missing %r', distribution, requirement) self.missing.setdefault(distribution, []).append(requirement) def _repr_dist(self, dist): return '%s %s' % (dist.name, dist.version) def repr_node(self, dist, level=1): """Prints only a subgraph""" output = [self._repr_dist(dist)] for other, label in self.adjacency_list[dist]: dist = self._repr_dist(other) if label is not None: dist = '%s [%s]' % (dist, label) output.append(' ' * level + str(dist)) suboutput = self.repr_node(other, level + 1) subs = suboutput.split('\n') output.extend(subs[1:]) return '\n'.join(output) def to_dot(self, f, skip_disconnected=True): """Writes a DOT output for the graph to the provided file *f*. If *skip_disconnected* is set to ``True``, then all distributions that are not dependent on any other distribution are skipped. :type f: has to support ``file``-like operations :type skip_disconnected: ``bool`` """ disconnected = [] f.write("digraph dependencies {\n") for dist, adjs in self.adjacency_list.items(): if len(adjs) == 0 and not skip_disconnected: disconnected.append(dist) for other, label in adjs: if not label is None: f.write('"%s" -> "%s" [label="%s"]\n' % (dist.name, other.name, label)) else: f.write('"%s" -> "%s"\n' % (dist.name, other.name)) if not skip_disconnected and len(disconnected) > 0: f.write('subgraph disconnected {\n') f.write('label = "Disconnected"\n') f.write('bgcolor = red\n') for dist in disconnected: f.write('"%s"' % dist.name) f.write('\n') f.write('}\n') f.write('}\n') def topological_sort(self): """ Perform a topological sort of the graph. :return: A tuple, the first element of which is a topologically sorted list of distributions, and the second element of which is a list of distributions that cannot be sorted because they have circular dependencies and so form a cycle. """ result = [] # Make a shallow copy of the adjacency list alist = {} for k, v in self.adjacency_list.items(): alist[k] = v[:] while True: # See what we can remove in this run to_remove = [] for k, v in list(alist.items())[:]: if not v: to_remove.append(k) del alist[k] if not to_remove: # What's left in alist (if anything) is a cycle. break # Remove from the adjacency list of others for k, v in alist.items(): alist[k] = [(d, r) for d, r in v if d not in to_remove] logger.debug('Moving to result: %s', ['%s (%s)' % (d.name, d.version) for d in to_remove]) result.extend(to_remove) return result, list(alist.keys()) def __repr__(self): """Representation of the graph""" output = [] for dist, adjs in self.adjacency_list.items(): output.append(self.repr_node(dist)) return '\n'.join(output) def make_graph(dists, scheme='default'): """Makes a dependency graph from the given distributions. :parameter dists: a list of distributions :type dists: list of :class:`distutils2.database.InstalledDistribution` and :class:`distutils2.database.EggInfoDistribution` instances :rtype: a :class:`DependencyGraph` instance """ scheme = get_scheme(scheme) graph = DependencyGraph() provided = {} # maps names to lists of (version, dist) tuples # first, build the graph and find out what's provided for dist in dists: graph.add_distribution(dist) for p in dist.provides: name, version = parse_name_and_version(p) logger.debug('Add to provided: %s, %s, %s', name, version, dist) provided.setdefault(name, []).append((version, dist)) # now make the edges for dist in dists: requires = (dist.run_requires | dist.meta_requires | dist.build_requires | dist.dev_requires) for req in requires: try: matcher = scheme.matcher(req) except UnsupportedVersionError: # XXX compat-mode if cannot read the version logger.warning('could not read version %r - using name only', req) name = req.split()[0] matcher = scheme.matcher(name) name = matcher.key # case-insensitive matched = False if name in provided: for version, provider in provided[name]: try: match = matcher.match(version) except UnsupportedVersionError: match = False if match: graph.add_edge(dist, provider, req) matched = True break if not matched: graph.add_missing(dist, req) return graph def get_dependent_dists(dists, dist): """Recursively generate a list of distributions from *dists* that are dependent on *dist*. :param dists: a list of distributions :param dist: a distribution, member of *dists* for which we are interested """ if dist not in dists: raise DistlibException('given distribution %r is not a member ' 'of the list' % dist.name) graph = make_graph(dists) dep = [dist] # dependent distributions todo = graph.reverse_list[dist] # list of nodes we should inspect while todo: d = todo.pop() dep.append(d) for succ in graph.reverse_list[d]: if succ not in dep: todo.append(succ) dep.pop(0) # remove dist from dep, was there to prevent infinite loops return dep def get_required_dists(dists, dist): """Recursively generate a list of distributions from *dists* that are required by *dist*. :param dists: a list of distributions :param dist: a distribution, member of *dists* for which we are interested """ if dist not in dists: raise DistlibException('given distribution %r is not a member ' 'of the list' % dist.name) graph = make_graph(dists) req = [] # required distributions todo = graph.adjacency_list[dist] # list of nodes we should inspect while todo: d = todo.pop()[0] req.append(d) for pred in graph.adjacency_list[d]: if pred not in req: todo.append(pred) return req def make_dist(name, version, **kwargs): """ A convenience method for making a dist given just a name and version. """ summary = kwargs.pop('summary', 'Placeholder for summary') md = Metadata(**kwargs) md.name = name md.version = version md.summary = summary or 'Placeholder for summary' return Distribution(md)


@ARTICLE{chen_spl20_gabf, author={B. -H. {Chen} and Y. -S. {Tseng} and J. -L. {Yin}}, journal={IEEE Signal Processing Letters}, title={Gaussian-Adaptive Bilateral Filter}, year={2020}, volume={27}, number={}, pages={1670-1674},}


Rich Xing
Oh my... how rich
Home
About
Rich Xing
Mandelbrot
Wireworld
Ezrean Dominion
2D Game
Pixi
Balcony
Black Mountain - Canberra
Both Her Faces - Sydney
City Lights
Civil Twilight - Canberra
Cloudfield
Haizhu
L1011F
Parked Car
Parramatta 80s
Parramatta Final
Prospect Substation
Redfern
Southern Sky - Melbourne
Takeoff
To a Little Radio


For over 20 years I dedicated myself to solving the technical and business problems and providing the very best customer service possible. Regardless of my position or title it is always about understanding the needs of the client and the challenges that stand in the way of them achieving their goals. From home users to the Fortune 500 companies around the world, I’ve solved problems big and small. As a consultant, support/escalation manager, and trainer I have primarily focused on Microsoft based infrastructure and server applications, networking, BlackBerry wireless messaging, and Google based solutions for business and schools.
I am opening a new chapter of my career as a student in the UIT Startup Immersion program at Cape Breton University. Upon completion of this program it is my plan to go on solving problems but on a much bigger scale.
I currently reside on the beautiful island of Cape Breton in the community of Scotchtown, Nova Scotia, Canada with partner Morene, our children and our dogs.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Fugiat, vitae, distinctio, possimus repudiandae cupiditate ipsum excepturi dicta neque eaque voluptates tempora veniam esse earum sapiente optio deleniti consequuntur eos voluptatem.


{% extends "base.html" %} {% block title %}
Medieval catalogues > UNIVERSITY AND COLLEGE LIBRARIES OF OXFORD > Corpus Christi College > List of books belonging to John Claymond, early 16th cent.
{% endif %}139 identified entries found.
All data was derived from the List of Identifications by Professor Richard Sharpe.
{% if not printing %}
A key to codes used in the List is available (opens in new tab).{% endif %}


{% extends 'mysite/base.html' %} {% block section %} {% if messages %}
Tickets Submitted
Tickets Rejected
Tickets Approved
Tickets Postponed
Tickets Resolved
Tickets Closed
Tickets Duplicated
Tickets Assigned


This sample demonstrates how to create a list-based widget specifically backed by a content provider.
Please make sure that you understand the earlier stack widget sample code before delving into this example
(see StackWidget).
As in the StackWidget example, we will be using a collection view (the ListView in this case) to present some mock weather data in a widget. In particular, we will be using a content provider to demonstrate how the widget can retrieve data and update itself when you are using more complex data sources. When working with external data, or data which must be fetched over high latency, it is important to keep the data cached in a persistent location so that the widget feels responsive.
This sample uses the following classes:
WeatherDataProvider
—
Our ContentProvider which stores the weather data for this sample. Note that for simplicity,
it currently stores the data in memory as opposed to an external and persistent storage such
as a file, network location, database, or shared preference.
WeatherWidgetProvider
—
Our AppWidgetProvider which handles specific intent actions (such as when an item is clicked,
or the refresh button is pressed). It also sets up the RemoteViews for the widget and binds
the service to the collection view in the widget.
WeatherWidgetService
—
Our RemoteViewsService which manages the creation of new factories, which return the RemoteViews
for each item in the ListView.
If you are writing collection-based widgets, remember that the feature is supported only on Android 3.0 (API level 11) and higher versions of the platform. Remember to add the following to the application's manifest publishing to Android Market:
<uses-sdk android:minSdkVersion="11" />
, which indicates
to Android Market and the platform that your application requires Android 3.0 or
higher. For more information, see the API Levels
and the documentation for the
<uses-sdk>
element.


Windows 10 November 2019 Update available through Windows Update Assistant
You can make sure you're system is up to date with the Update Assistant.
by Sean EndicottSource: Windows Central
What you need to know
- The Windows Update Assistant can now update your PC to the Windows 10 November 2019 Update.
- The assistant is useful for people whose devices haven't received the update yet.
- The Windows 10 November 2019 Update is similar to a service pack, focusing on improving an existing version of Windows 10.
You can now update your PC to the Windows 10 November 2019 Update using the Windows Update Assistant (via MSPU). The tool allows you to upgrade your PC even if your system hasn't seen the latest update automatically. You can download the Update Assistant directly from Microsoft to get the latest update.
The Windows 10 November 2019 Update, also known as Windows 10 version 1909, focuses mainly on fixing bugs and building on top of previous versions of Windows 10. Rather than bringing a wide range of new features like some feature updates, Windows 10 version 1909 acts like a service pack.
While the update doesn't have many new features, it's still worth grabbing now. Our Senior Editor Zac Bowden said in his review of the update "This is a Windows 10 feature update you should be comfortable with installing because it's incredibly stable, has a few excellent additions that improve the overall user experience, and isn't as much of a risk to install."
We may earn a commission for purchases using our links. Learn more.


8 September 2004
From 22 May - 27 August 2004 a total of 3753 cases and 55 deaths of suspected hepatitis E was reported from health clinics in the Greater Darfur region through the early warning alert and response system (EWARN).
West Darfur remains the most affected area reporting 73% of the total reported cases. There is a slight decrease in the total number of cases reported from South and West Darfur, whilst cases in North Darfur have increased slightly. The preliminary phase of field investigations conducted by Epicentre and EPIET (European Programme for Intervention Epidemiology Training) to assess the epidemiology of hepatitis E and to focus on the most appropriate prevention and control measures has been completed.
UNICEF has continued to work with federal and state ministries of health and nongovernmental organizations to increase the quality and quantity of the water supply. In West Darfur, Concern Worldwide International has established public health teams and completed the construction of 1000 latrines in Mornei. In the accessible part of South Darfur, WHO has worked closely with the Health and Hygiene Working Group in the area to develop strategies for delivering consistent health messages for community health education in the IDP camps for internally displaced people, particularly targeting pregnant women and other high risk groups.
Despite these efforts, existing resources remain insufficient to cover the basic water and sanitation needs of the displaced populations in Darfur. Additional efforts are still needed improve access to safe, clean water and better sanitation in the camps in order to stop spread and reduce the number of new infections.


|
SideCar
|
User-defined view setting. More...
#include </Users/howes/src/sidecar/GUI/AScope/ViewSettings.h>
Public Member Functions | |
| ViewSettings (double rangeMin, double rangeMax, int gateMin, int gateMax, double voltageMin, double voltageMax, int sampleMin, int sampleMax, bool showingRanges, bool showingVoltages) | |
| ViewSettings (QSettings &settings) | |
| const ViewBounds & | getBounds () const |
| void | setBounds (const ViewBounds &bounds) |
| double | getRangeMin () const |
| double | getRangeMax () const |
| int | getGateMin () const |
| int | getGateMax () const |
| double | getVoltageMin () const |
| double | getVoltageMax () const |
| int | getSampleMin () const |
| int | getSampleMax () const |
| bool | isShowingRanges () const |
| void | setShowingRanges (bool state) |
| bool | isShowingVoltages () const |
| void | setShowingVoltages (bool state) |
| void | restoreFromSettings (QSettings &settings) |
| void | saveToSettings (QSettings &settings) const |
| bool | operator== (const ViewSettings &rhs) const |
| bool | operator!= (const ViewSettings &rhs) const |
Static Public Member Functions | |
| static Logger::Log & | Log () |
User-defined view setting.
Definition at line 43 of file ViewSettings.h.


Mart
Home
About us
Page
Shop
Blog
Contact us
left
right
Affortable Paris tours
City tours/tour tickets/tour guider
New collection
like
change
time
add to cart
Blue tshirt
$26
like
change
time
add to cart
Woman shirt
$31
like
change
time
add to cart
Yellow tshirt
$21
like
change
time
add to cart
Cool lingerie
$56


Last updated and effective: March 28, 2021
Owner and data controller: Antti.Codes
Contact email<EMAIL_ADDRESS>Antti.Codes provides a Discord chat bot (the "Bot"), and a website (the "Site") and related services (collectively, the "Service(s)"). The Service is operated by Antti.Codes. (the "Company", "we" or "us") for users of the Service ("you"). This Privacy Policy sets forth our policy with respect to information that is collected from visitors to the Site and users of the bot and/or the Services. Under applicable law, Antti.Codes is the “data controller” of personal data collected through the Services.
When you interact with us through the Services, we may collect information from you, as further described below:
Information You Provide: We collect information from you when you voluntarily provide such information, such as when you use any of the Services.
Information we collect may include but not be limited to usage data, usernames, or other content you send to us by interacting with the Bot.
The Company is based in Finland and the Services are hosted in Germany (by Contabo GmbH). No matter where you are located, you consent to the processing and transferring of your information in and to Finland, Germany and other countries. The laws of Finland, Germany and other countries governing data collection and use may not be as comprehensive or protective as the laws of the country where you live.
We use the information you provide in a manner that is consistent with this Privacy Policy. If you provide information for a certain reason, we may use the information in connection with the reason for which it was provided. For instance, if you contact us by email, we will use the information you provide to answer your question or resolve your problem. Also, if you provide information in order to obtain access to the Services, we will use your information to provide you with access to such services and to monitor your use of such services. The Company and its subsidiaries and affiliates (the "Related Companies") may also use your information collected through the Services to help us improve the content and functionality of the Services, to better understand our users and to improve the Services.
The laws in some jurisdictions require companies to tell you about the legal ground they rely on to use or disclose your personal data. To the extent those laws apply, our legal grounds are as follows:
The Company is not in the business of selling your information. We consider this information to be a vital part of our relationship with you. There are, however, certain circumstances in which we may share your information with certain third parties, as set forth below:
You may provide us with ideas for new products or modifications to existing products, and other unsolicited submissions (collectively, "Unsolicited Information"). All Unsolicited Information shall be deemed to be non-confidential and we shall be free to reproduce, use, disclose, and distribute such Unsolicited Information to others without limitation or attribution.
Our Services are for users age 13 and over and we do not knowingly collect personal information from children under the age of 13. If you are a parent or guardian of a child under the age of 13 and believe he or she has disclosed personal information to us please contact us at<EMAIL_ADDRESS>Note: In some countries, the age of digital consent is older than 13. If you are in those countries, you must be at least that age to use the Services. For example, for residents of the EEA, where processing of personal information is based on consent, Antti.Codes will not knowingly engage in that processing for users under the age of consent established by applicable data protection law. If we learn that we are engaged in that processing with such users, we will halt such processing and will take reasonable measures to promptly remove applicable information from our records.
This Privacy Policy applies only to the Services. The Services may contain links to other web sites not operated or controlled by us (the "Third Party Sites"). The policies and procedures we described here do not apply to the Third Party Sites. The links from the Services do not imply that we endorse or have reviewed the Third Party Sites. We suggest contacting those sites directly for information on their privacy policies.
We generally retain personal data for so long as it may be relevant to the purposes identified herein. To dispose of personal data, we may anonymize it, delete it or take other appropriate steps. Data may persist in copies made for backup and business continuity purposes for additional time.
We take reasonable steps to protect the information provided via the Services from loss, misuse, and unauthorized access, disclosure, alteration, or destruction. However, no Internet or email transmission is ever fully secure or error free. In particular, email sent to or from the Services may not be secure. Therefore, you should take special care in deciding what information you send to us via email. Please keep this in mind when disclosing any information via the Internet.
We believe that users should be treated equally no matter where they are,
and so we are making the following options to control your data available to all users, regardless of their location.
Individuals in California, the European Economic Area, Canada, Costa Rica and some other jurisdictions outside the United States have certain
legal rights to obtain confirmation of whether we hold personal data about them, to access personal data we hold about them (including, in some cases, in portable form),
and to obtain its correction, update, amendment or deletion in appropriate circumstances. They may also object to our uses or disclosures of personal data,
to request a restriction on its processing, or withdraw any consent, though such actions typically will not have retroactive effect.
They also will not affect our ability to continue processing data in lawful ways.
We reserve the right to update or modify this Privacy Policy at any time and from time to time without prior notice. Please review this policy periodically, and especially before you provide any information. This Privacy Policy was last updated on the date indicated above. Your continued use of the Services after any changes or revisions to this Privacy Policy shall indicate your agreement with the terms of such revised Privacy Policy.
Please also feel free to contact us if you have any questions about this Privacy Policy or the information practices of the Services. You may contact us as follows: antti@antti.codes.


--- title: null program Turns Two Years Old layout: post tags: [meta] uuid: 5c47675e-fe5c-3ae4-a5e9-c8252b729276 ---
This website/blog turns two years old today. That's right, the first post was on September 1, 2007. This also happens to be the 100th post! Woo! Which means I have nearly kept up with my original one post per week planned average (104 would put me on schedule).
The site has evolved a bit in that time. Two years ago I was using vanilla blosxom (I've since hacked it up), no comments, no portrait (portraits increase reader trust), simpler logo, no color, no RSS (it was there, but I wasn't linking it), crappy index, no features but this blog and the "projects" section, no Creative Commons license (but I've always had the other simple copyleft statement), no lisp, and only one permalink per post. Since I started this site I lived in three different US states, had two different jobs, bought two computers, bought a car, adopted a cat, learned several programming languages, graduated with a bachelor's degree, had major surgery, and got married.
I've tried to make all my posts more than a trivial "hey, check this link out", and instead have some real content for each one. Thanks to this, if you concatenate all the posts together it's long enough to be a short book (about 170 pages). And, this blog is 100% Free Culture. All text and images are public domain or under a Free license (and none of that non-commercial-only crap). So I — or anyone — could easily publish it as a book. (Ha! As if anyone would buy it!) And I do maintain another completely separate blog, with a (currently) higher post frequency, under a pseudonym (so I don't get myself into trouble), which is why I won't tell you what it is. :-)
I'm really happy I kept kept this "log" of my activities. I've had some real misconceptions about my previous self, which the log has cleared up. I often think I came up with ideas or had viewpoints much more recently than I really did ("Oh, learning Scheme really was that long ago."). I wish it went back further, because, for example, I really am not sure at which point I became an atheist (early 2003?) or a left libertarian (summer 2003?).  I know one one thing for sure, my writing hasn't really improved!
So, thanks for reading! If you don't already have a blog, start one today. Keep up with it, and at two years I'm sure you'll be really glad you have it.
Here's to another two years!


{% extends 'layout.html' %} {% block content %}
Dear {{ message_content.get('name', '')|title }},
Thank you for contacting us. Our representative will get back to you in next 24 hours to know more about your needs. Meanwhile you can search through our list of available spaces as per your need from Here


rotten > Library > Biographies > Religion > Cult leaders > Jim Jones
Jim Jones
Failed monkey salesman.
Despite his sociopathy, one must give Jim Jones mad props for loyalty and people management skills. First, he transforms his seemingly mainstream San Francisco congregation into a full-blown religious cult. Next he convinces the government of Guyana to give him 300 acres of South American jungle, and relocates 1,100 cult members to this distant hellhole. Finally, in 1978 after it all goes horribly wrong, Jones still manages to convince 900 of them to swallow poison in massively parallel suicide, the likes of which the world had never seen.
Arrested in a cruisy restroom in Los Angeles.
By the way, it wasn't Kool-Aid. It was Flavor Aid®. Different company altogether.
Timeline
| 13 Dec 1973 |
The Reverend Jim Jones is arrested in a cruisy movie theater bathroom in Los Angeles. Unfortunately, Jones had the bad luck to hit on an undercover LAPD vice officer while masturbating in the Westlake Theatre men's room. |
| 5 Oct 1976 |
Bob Houston is pushed under a train, the day after announcing his intention to leave the People's Temple. |
| 18 Nov 1978 |
The assassination of Congressman Leo J. Ryan and the 900-person mass suicide at Jonestown, Guyana. |
| 1989 |
The abandoned People's Temple building on Geary and Steiner in San Francisco is razed following the Loma Prieta earthquake. A post office now stands in its place. |
Pornopolis |
Rotten |
Faces of Death |
Famous Nudes
|


--- layout: post title: "My Week in Review" date: 2017-07-30 07:45:00 +0000 tags: image: https://s3.amazonaws.com/audreywatters/2017-07-30-gull.jpg imagecredits: https://www.flickr.com/photos/bertknot/8121038527 ---
Icon credits: The Noun Project


Palabraset? Wortset? Motset? – Expanding beyond English
Wordset is expanding fast. We've got a lot of great people helping on projects, improving definitions, and adding example sentences. All of this is to help build the first open, collaborative English dictionary.
English isn’t the only language, though. We want to expand as soon as possible into other languages, but unfortunately Hampton and I only speak one.
That's why we’re looking for volunteers to help us expand into new target languages (TLs). Here's some of the ways in which you could help:
If you can help, please fill out a form explaining which language(s) you could help out with. We've listed out the top 20 languages according to Wikipedia, but would be open to other languages if the interest and community is there.
Note that as well as the target language, you would have to be familiar with English in order to communicate with Hampton and me (but I assume that if you're reading this, that won't be too much of a problem).
Looking forward to seeing which languages we'll tackle next!
– Hampton and Michael


Приложение доступно на устройствах с шириной экрана от 568 пикселей и выше. Для просмотра контента подойдет девайс не меньше, чем iPad mini. Приносим свои извинения за предоставленные неудобства.
Orthogonal latin squares
The construction of 4x4 set was published by Jacques Ozanam in 1725
as a puzzle involving playing cards.
The problem was to take all aces, kings, queens and jacks from a standard deck of cards,
and arrange them in a 4x4 grid such that each row and each column contained all four
suits as well as one of each face value.


Hello ! I'm a Web Developer from Cherry Hill, New Jersey. I primarily program in Javascript but I am learning Python currently. Please check out my Resume, Linkedin, or Github below, along with my projects.
I have always loved puzzles and doing things that challenge my brain. I decided to learn programming because of an enthusiastic friend and I am happier than ever. I have always had an interest in tech from playing the original NES to building custom PCs. Now I'm working in it and creating new things as a career (please check out my projects below!). Programming to me is like building and putting together a giant puzzle without any limits.
609-560-3617
9am-7pm