1639491797
In this tutorial, we will talk a little bit about pods and a little bit about accessing them using the magical NodePort.
Note: Before you proceed, make sure you know the basic architecture of Kubernetes and the corresponding commands and the structure of yaml files in Kubernetes.
I am assuming most of us know what pods are but in case you don’t, it is the smallest unit in Kubernetes and is essentially what holds the docker containers running applications. Consider it as a little box.
1602964260
Last year, we provided a list of Kubernetes tools that proved so popular we have decided to curate another list of some useful additions for working with the platform—among which are many tools that we personally use here at Caylent. Check out the original tools list here in case you missed it.
According to a recent survey done by Stackrox, the dominance Kubernetes enjoys in the market continues to be reinforced, with 86% of respondents using it for container orchestration.
(State of Kubernetes and Container Security, 2020)
And as you can see below, more and more companies are jumping into containerization for their apps. If you’re among them, here are some tools to aid you going forward as Kubernetes continues its rapid growth.
(State of Kubernetes and Container Security, 2020)
#blog #tools #amazon elastic kubernetes service #application security #aws kms #botkube #caylent #cli #container monitoring #container orchestration tools #container security #containers #continuous delivery #continuous deployment #continuous integration #contour #developers #development #developments #draft #eksctl #firewall #gcp #github #harbor #helm #helm charts #helm-2to3 #helm-aws-secret-plugin #helm-docs #helm-operator-get-started #helm-secrets #iam #json #k-rail #k3s #k3sup #k8s #keel.sh #keycloak #kiali #kiam #klum #knative #krew #ksniff #kube #kube-prod-runtime #kube-ps1 #kube-scan #kube-state-metrics #kube2iam #kubeapps #kubebuilder #kubeconfig #kubectl #kubectl-aws-secrets #kubefwd #kubernetes #kubernetes command line tool #kubernetes configuration #kubernetes deployment #kubernetes in development #kubernetes in production #kubernetes ingress #kubernetes interfaces #kubernetes monitoring #kubernetes networking #kubernetes observability #kubernetes plugins #kubernetes secrets #kubernetes security #kubernetes security best practices #kubernetes security vendors #kubernetes service discovery #kubernetic #kubesec #kubeterminal #kubeval #kudo #kuma #microsoft azure key vault #mozilla sops #octant #octarine #open source #palo alto kubernetes security #permission-manager #pgp #rafay #rakess #rancher #rook #secrets operations #serverless function #service mesh #shell-operator #snyk #snyk container #sonobuoy #strongdm #tcpdump #tenkai #testing #tigera #tilt #vert.x #wireshark #yaml
1667425440
Perl script converts PDF files to Gerber format
Pdf2Gerb generates Gerber 274X photoplotting and Excellon drill files from PDFs of a PCB. Up to three PDFs are used: the top copper layer, the bottom copper layer (for 2-sided PCBs), and an optional silk screen layer. The PDFs can be created directly from any PDF drawing software, or a PDF print driver can be used to capture the Print output if the drawing software does not directly support output to PDF.
The general workflow is as follows:
Please note that Pdf2Gerb does NOT perform DRC (Design Rule Checks), as these will vary according to individual PCB manufacturer conventions and capabilities. Also note that Pdf2Gerb is not perfect, so the output files must always be checked before submitting them. As of version 1.6, Pdf2Gerb supports most PCB elements, such as round and square pads, round holes, traces, SMD pads, ground planes, no-fill areas, and panelization. However, because it interprets the graphical output of a Print function, there are limitations in what it can recognize (or there may be bugs).
See docs/Pdf2Gerb.pdf for install/setup, config, usage, and other info.
#Pdf2Gerb config settings:
#Put this file in same folder/directory as pdf2gerb.pl itself (global settings),
#or copy to another folder/directory with PDFs if you want PCB-specific settings.
#There is only one user of this file, so we don't need a custom package or namespace.
#NOTE: all constants defined in here will be added to main namespace.
#package pdf2gerb_cfg;
use strict; #trap undef vars (easier debug)
use warnings; #other useful info (easier debug)
##############################################################################################
#configurable settings:
#change values here instead of in main pfg2gerb.pl file
use constant WANT_COLORS => ($^O !~ m/Win/); #ANSI colors no worky on Windows? this must be set < first DebugPrint() call
#just a little warning; set realistic expectations:
#DebugPrint("${\(CYAN)}Pdf2Gerb.pl ${\(VERSION)}, $^O O/S\n${\(YELLOW)}${\(BOLD)}${\(ITALIC)}This is EXPERIMENTAL software. \nGerber files MAY CONTAIN ERRORS. Please CHECK them before fabrication!${\(RESET)}", 0); #if WANT_DEBUG
use constant METRIC => FALSE; #set to TRUE for metric units (only affect final numbers in output files, not internal arithmetic)
use constant APERTURE_LIMIT => 0; #34; #max #apertures to use; generate warnings if too many apertures are used (0 to not check)
use constant DRILL_FMT => '2.4'; #'2.3'; #'2.4' is the default for PCB fab; change to '2.3' for CNC
use constant WANT_DEBUG => 0; #10; #level of debug wanted; higher == more, lower == less, 0 == none
use constant GERBER_DEBUG => 0; #level of debug to include in Gerber file; DON'T USE FOR FABRICATION
use constant WANT_STREAMS => FALSE; #TRUE; #save decompressed streams to files (for debug)
use constant WANT_ALLINPUT => FALSE; #TRUE; #save entire input stream (for debug ONLY)
#DebugPrint(sprintf("${\(CYAN)}DEBUG: stdout %d, gerber %d, want streams? %d, all input? %d, O/S: $^O, Perl: $]${\(RESET)}\n", WANT_DEBUG, GERBER_DEBUG, WANT_STREAMS, WANT_ALLINPUT), 1);
#DebugPrint(sprintf("max int = %d, min int = %d\n", MAXINT, MININT), 1);
#define standard trace and pad sizes to reduce scaling or PDF rendering errors:
#This avoids weird aperture settings and replaces them with more standardized values.
#(I'm not sure how photoplotters handle strange sizes).
#Fewer choices here gives more accurate mapping in the final Gerber files.
#units are in inches
use constant TOOL_SIZES => #add more as desired
(
#round or square pads (> 0) and drills (< 0):
.010, -.001, #tiny pads for SMD; dummy drill size (too small for practical use, but needed so StandardTool will use this entry)
.031, -.014, #used for vias
.041, -.020, #smallest non-filled plated hole
.051, -.025,
.056, -.029, #useful for IC pins
.070, -.033,
.075, -.040, #heavier leads
# .090, -.043, #NOTE: 600 dpi is not high enough resolution to reliably distinguish between .043" and .046", so choose 1 of the 2 here
.100, -.046,
.115, -.052,
.130, -.061,
.140, -.067,
.150, -.079,
.175, -.088,
.190, -.093,
.200, -.100,
.220, -.110,
.160, -.125, #useful for mounting holes
#some additional pad sizes without holes (repeat a previous hole size if you just want the pad size):
.090, -.040, #want a .090 pad option, but use dummy hole size
.065, -.040, #.065 x .065 rect pad
.035, -.040, #.035 x .065 rect pad
#traces:
.001, #too thin for real traces; use only for board outlines
.006, #minimum real trace width; mainly used for text
.008, #mainly used for mid-sized text, not traces
.010, #minimum recommended trace width for low-current signals
.012,
.015, #moderate low-voltage current
.020, #heavier trace for power, ground (even if a lighter one is adequate)
.025,
.030, #heavy-current traces; be careful with these ones!
.040,
.050,
.060,
.080,
.100,
.120,
);
#Areas larger than the values below will be filled with parallel lines:
#This cuts down on the number of aperture sizes used.
#Set to 0 to always use an aperture or drill, regardless of size.
use constant { MAX_APERTURE => max((TOOL_SIZES)) + .004, MAX_DRILL => -min((TOOL_SIZES)) + .004 }; #max aperture and drill sizes (plus a little tolerance)
#DebugPrint(sprintf("using %d standard tool sizes: %s, max aper %.3f, max drill %.3f\n", scalar((TOOL_SIZES)), join(", ", (TOOL_SIZES)), MAX_APERTURE, MAX_DRILL), 1);
#NOTE: Compare the PDF to the original CAD file to check the accuracy of the PDF rendering and parsing!
#for example, the CAD software I used generated the following circles for holes:
#CAD hole size: parsed PDF diameter: error:
# .014 .016 +.002
# .020 .02267 +.00267
# .025 .026 +.001
# .029 .03167 +.00267
# .033 .036 +.003
# .040 .04267 +.00267
#This was usually ~ .002" - .003" too big compared to the hole as displayed in the CAD software.
#To compensate for PDF rendering errors (either during CAD Print function or PDF parsing logic), adjust the values below as needed.
#units are pixels; for example, a value of 2.4 at 600 dpi = .0004 inch, 2 at 600 dpi = .0033"
use constant
{
HOLE_ADJUST => -0.004 * 600, #-2.6, #holes seemed to be slightly oversized (by .002" - .004"), so shrink them a little
RNDPAD_ADJUST => -0.003 * 600, #-2, #-2.4, #round pads seemed to be slightly oversized, so shrink them a little
SQRPAD_ADJUST => +0.001 * 600, #+.5, #square pads are sometimes too small by .00067, so bump them up a little
RECTPAD_ADJUST => 0, #(pixels) rectangular pads seem to be okay? (not tested much)
TRACE_ADJUST => 0, #(pixels) traces seemed to be okay?
REDUCE_TOLERANCE => .001, #(inches) allow this much variation when reducing circles and rects
};
#Also, my CAD's Print function or the PDF print driver I used was a little off for circles, so define some additional adjustment values here:
#Values are added to X/Y coordinates; units are pixels; for example, a value of 1 at 600 dpi would be ~= .002 inch
use constant
{
CIRCLE_ADJUST_MINX => 0,
CIRCLE_ADJUST_MINY => -0.001 * 600, #-1, #circles were a little too high, so nudge them a little lower
CIRCLE_ADJUST_MAXX => +0.001 * 600, #+1, #circles were a little too far to the left, so nudge them a little to the right
CIRCLE_ADJUST_MAXY => 0,
SUBST_CIRCLE_CLIPRECT => FALSE, #generate circle and substitute for clip rects (to compensate for the way some CAD software draws circles)
WANT_CLIPRECT => TRUE, #FALSE, #AI doesn't need clip rect at all? should be on normally?
RECT_COMPLETION => FALSE, #TRUE, #fill in 4th side of rect when 3 sides found
};
#allow .012 clearance around pads for solder mask:
#This value effectively adjusts pad sizes in the TOOL_SIZES list above (only for solder mask layers).
use constant SOLDER_MARGIN => +.012; #units are inches
#line join/cap styles:
use constant
{
CAP_NONE => 0, #butt (none); line is exact length
CAP_ROUND => 1, #round cap/join; line overhangs by a semi-circle at either end
CAP_SQUARE => 2, #square cap/join; line overhangs by a half square on either end
CAP_OVERRIDE => FALSE, #cap style overrides drawing logic
};
#number of elements in each shape type:
use constant
{
RECT_SHAPELEN => 6, #x0, y0, x1, y1, count, "rect" (start, end corners)
LINE_SHAPELEN => 6, #x0, y0, x1, y1, count, "line" (line seg)
CURVE_SHAPELEN => 10, #xstart, ystart, x0, y0, x1, y1, xend, yend, count, "curve" (bezier 2 points)
CIRCLE_SHAPELEN => 5, #x, y, 5, count, "circle" (center + radius)
};
#const my %SHAPELEN =
#Readonly my %SHAPELEN =>
our %SHAPELEN =
(
rect => RECT_SHAPELEN,
line => LINE_SHAPELEN,
curve => CURVE_SHAPELEN,
circle => CIRCLE_SHAPELEN,
);
#panelization:
#This will repeat the entire body the number of times indicated along the X or Y axes (files grow accordingly).
#Display elements that overhang PCB boundary can be squashed or left as-is (typically text or other silk screen markings).
#Set "overhangs" TRUE to allow overhangs, FALSE to truncate them.
#xpad and ypad allow margins to be added around outer edge of panelized PCB.
use constant PANELIZE => {'x' => 1, 'y' => 1, 'xpad' => 0, 'ypad' => 0, 'overhangs' => TRUE}; #number of times to repeat in X and Y directions
# Set this to 1 if you need TurboCAD support.
#$turboCAD = FALSE; #is this still needed as an option?
#CIRCAD pad generation uses an appropriate aperture, then moves it (stroke) "a little" - we use this to find pads and distinguish them from PCB holes.
use constant PAD_STROKE => 0.3; #0.0005 * 600; #units are pixels
#convert very short traces to pads or holes:
use constant TRACE_MINLEN => .001; #units are inches
#use constant ALWAYS_XY => TRUE; #FALSE; #force XY even if X or Y doesn't change; NOTE: needs to be TRUE for all pads to show in FlatCAM and ViewPlot
use constant REMOVE_POLARITY => FALSE; #TRUE; #set to remove subtractive (negative) polarity; NOTE: must be FALSE for ground planes
#PDF uses "points", each point = 1/72 inch
#combined with a PDF scale factor of .12, this gives 600 dpi resolution (1/72 * .12 = 600 dpi)
use constant INCHES_PER_POINT => 1/72; #0.0138888889; #multiply point-size by this to get inches
# The precision used when computing a bezier curve. Higher numbers are more precise but slower (and generate larger files).
#$bezierPrecision = 100;
use constant BEZIER_PRECISION => 36; #100; #use const; reduced for faster rendering (mainly used for silk screen and thermal pads)
# Ground planes and silk screen or larger copper rectangles or circles are filled line-by-line using this resolution.
use constant FILL_WIDTH => .01; #fill at most 0.01 inch at a time
# The max number of characters to read into memory
use constant MAX_BYTES => 10 * M; #bumped up to 10 MB, use const
use constant DUP_DRILL1 => TRUE; #FALSE; #kludge: ViewPlot doesn't load drill files that are too small so duplicate first tool
my $runtime = time(); #Time::HiRes::gettimeofday(); #measure my execution time
print STDERR "Loaded config settings from '${\(__FILE__)}'.\n";
1; #last value must be truthful to indicate successful load
#############################################################################################
#junk/experiment:
#use Package::Constants;
#use Exporter qw(import); #https://perldoc.perl.org/Exporter.html
#my $caller = "pdf2gerb::";
#sub cfg
#{
# my $proto = shift;
# my $class = ref($proto) || $proto;
# my $settings =
# {
# $WANT_DEBUG => 990, #10; #level of debug wanted; higher == more, lower == less, 0 == none
# };
# bless($settings, $class);
# return $settings;
#}
#use constant HELLO => "hi there2"; #"main::HELLO" => "hi there";
#use constant GOODBYE => 14; #"main::GOODBYE" => 12;
#print STDERR "read cfg file\n";
#our @EXPORT_OK = Package::Constants->list(__PACKAGE__); #https://www.perlmonks.org/?node_id=1072691; NOTE: "_OK" skips short/common names
#print STDERR scalar(@EXPORT_OK) . " consts exported:\n";
#foreach(@EXPORT_OK) { print STDERR "$_\n"; }
#my $val = main::thing("xyz");
#print STDERR "caller gave me $val\n";
#foreach my $arg (@ARGV) { print STDERR "arg $arg\n"; }
Author: swannman
Source Code: https://github.com/swannman/pdf2gerb
License: GPL-3.0 license
1666454701
By XMARTLABS.
XLActionController is an extensible library to quickly create any custom action sheet controller.
![]() | ![]() | ![]() |
![]() | ![]() | ![]() |
The action sheet controllers shown above were entirely created using XLActionController and are included in the Examples. To run the Example project: clone XLActionController repository, open XLActionController workspace and run the Example project.
The code snippet below shows how to present the Tweetbot action sheet controller:
let actionController = TweetbotActionController()
actionController.addAction(Action("View Details", style: .default, handler: { action in
// do something useful
}))
actionController.addAction(Action("View Retweets", style: .default, handler: { action in
// do something useful
}))
actionController.addAction(Action("View in Favstar", style: .default, handler: { action in
// do something useful
}))
actionController.addAction(Action("Translate", style: .default, executeImmediatelyOnTouch: true, handler: { action in
// do something useful
}))
actionController.addSection(Section())
actionController.addAction(Action("Cancel", style: .cancel, handler:nil))
present(actionController, animated: true, completion: nil)
As you may have noticed, the library usage looks pretty similar to UIAlertController.
Actions' handlers are executed after the alert controller is dismissed from screen. If you want, you can change this passing true
to the action's constructor to the argument executeImmediatelyOnTouch
.
Behind the scenes XLActionController uses a UICollectionView to display the action sheet.
First create a custom action sheet view controller by extending from the ActionController
generic class. For details on how to create a custom action sheet controller look at the Extensibility section.
For instance, let's suppose we've already created TwitterActionController
.
// Instantiate custom action sheet controller
let actionSheet = TwitterActionController()
// set up a header title
actionSheet.headerData = "Accounts"
// Add some actions, note that the first parameter of `Action` initializer is `ActionData`.
actionSheet.addAction(Action(ActionData(title: "Xmartlabs", subtitle: "@xmartlabs", image: UIImage(named: "tw-xmartlabs")!), style: .default, handler: { action in
// do something useful
}))
actionSheet.addAction(Action(ActionData(title: "Miguel", subtitle: "@remer88", image: UIImage(named: "tw-remer")!), style: .default, handler: { action in
// do something useful
}))
// present actionSheet like any other view controller
present(actionSheet, animated: true, completion: nil)
As the code above illustrates, there are no relevant differences compared to the UIAlertController API.
The main difference is that XLActionController works with any header data type and not only the standard UIAlertController title
and message
properties. Similarly XLActionController's Action works with any data Type and not only the title
string.
// XLActionController:
xlActionController.headerData = SpotifyHeaderData(title: "The Fast And The Furious Soundtrack Collection", subtitle: "Various Artists", image: UIImage(named: "sp-header-icon")!)
// vs UIAlertController:
uiActionController.title = "The Fast And The Furious Soundtrack Collection" // no way to pass an image
uiActionController.message = "Various Artists"
// XLActionController:
let xlAction = Action(ActionData(title: "Save Full Album", image: UIImage(named: "sp-add-icon")!), style: .default, handler: { action in })
// notice that we are able to pass an image in addition to the title
xlActionController.addAction(xlAction)
// vs UIAlertController:
let uiAction = UIAlertAction(title: "Xmartlabs", style: .default, handler: { action in }))
uiActionController.addAction(uiAction)
This can be accomplished because XLActionController is a generic type.
Another important difference is that XLActionController provides a way to add action sections as illustrated in the code below:
actionController.addSection(Section())
and also each section has a data
property. This property is generic, so that it can hold any type. This data will be used to create this section's header view.
let section = actionController.addSection(Section())
section.data = "String" // assuming section data Type is String
Each section contains a set of actions. We typically use sections to show a header view above a set of actions.
ActionController uses a UICollectionView to show actions and headers on screen. Actions will be rendered as instances of UICollectionViewCell. You can use your own subclass of UICollectionViewCell by specifying it in the action controller declaration. Additionally, ActionController allows you to specify a global header and a section header. Headers are shown as collection view's supplementary views.
The ActionController
class is a generic type that works with any cell, header, section header type and its associated data types.
XLActionController provides extension points to specify a whole new look and feel to our custom sheet controller and to tweak present and dismiss animations. Let's see an example:
// As first step we should extend the ActionController generic type
public class PeriscopeActionController: ActionController<PeriscopeCell, String, PeriscopeHeader, String, UICollectionReusableView, Void> {
// override init in order to customize behavior and animations
public override init(nibName nibNameOrNil: String? = nil, bundle nibBundleOrNil: Bundle? = nil) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
// customizing behavior and present/dismiss animations
settings.behavior.hideOnScrollDown = false
settings.animation.scale = nil
settings.animation.present.duration = 0.6
settings.animation.dismiss.duration = 0.5
settings.animation.dismiss.options = .curveEaseIn
settings.animation.dismiss.offset = 30
// providing a specific collection view cell which will be used to display each action, height parameter expects a block that returns the cell height for a particular action.
cellSpec = .nibFile(nibName: "PeriscopeCell", bundle: Bundle(for: PeriscopeCell.self), height: { _ in 60})
// providing a specific view that will render each section header.
sectionHeaderSpec = .cellClass(height: { _ in 5 })
// providing a specific view that will render the action sheet header. We calculate its height according the text that should be displayed.
headerSpec = .cellClass(height: { [weak self] (headerData: String) in
guard let me = self else { return 0 }
let label = UILabel(frame: CGRect(x: 0, y: 0, width: me.view.frame.width - 40, height: CGFloat.greatestFiniteMagnitude))
label.numberOfLines = 0
label.font = .systemFontOfSize(17.0)
label.text = headerData
label.sizeToFit()
return label.frame.size.height + 20
})
// once we specify the views, we have to provide three blocks that will be used to set up these views.
// block used to setup the header. Header view and the header are passed as block parameters
onConfigureHeader = { [weak self] header, headerData in
guard let me = self else { return }
header.label.frame = CGRect(x: 0, y: 0, width: me.view.frame.size.width - 40, height: CGFloat.greatestFiniteMagnitude)
header.label.text = headerData
header.label.sizeToFit()
header.label.center = CGPoint(x: header.frame.size.width / 2, y: header.frame.size.height / 2)
}
// block used to setup the section header
onConfigureSectionHeader = { sectionHeader, sectionHeaderData in
sectionHeader.backgroundColor = UIColor(white: 0.95, alpha: 1.0)
}
// block used to setup the collection view cell
onConfigureCellForAction = { [weak self] cell, action, indexPath in
cell.setup(action.data, detail: nil, image: nil)
cell.separatorView?.isHidden = indexPath.item == self!.collectionView.numberOfItems(inSection: indexPath.section) - 1
cell.alpha = action.enabled ? 1.0 : 0.5
cell.actionTitleLabel?.textColor = action.style == .destructive ? UIColor(red: 210/255.0, green: 77/255.0, blue: 56/255.0, alpha: 1.0) : UIColor(red: 0.28, green: 0.64, blue: 0.76, alpha: 1.0)
}
}
}
ActionController type declaration:
public class ActionController<ActionViewType: UICollectionViewCell, ActionDataType, HeaderViewType: UICollectionReusableView, HeaderDataType, SectionHeaderViewType: UICollectionReusableView, SectionHeaderDataType>
When extending ActionController we must specify the following view types ActionViewType, HeaderViewType, SectionHeaderViewType. These types are the cell type used to render an action, the view used to render the action sheet header and the view used to render the section header.
Each view type has its associated data: ActionDataType, HeaderDataType, SectionHeaderDataType respectively.
If your custom action sheet doesn't have a header view we can use
UICollectionReusableView
asHeaderViewType
andVoid
asHeaderDataType
. If it doesn't have a section header view you can useUICollectionReusableView
asSectionHeaderViewType
andVoid
asSectionHeaderDataType
.
The code below shows how we specify these types for the action controllers provided in the example project:
class PeriscopeActionController: ActionController<PeriscopeCell, String, PeriscopeHeader, String, UICollectionReusableView, Void> { ... } // doesn't need to show a section header
class SpotifyActionController: ActionController<SpotifyCell, ActionData, SpotifyHeaderView, SpotifyHeaderData, UICollectionReusableView, Void> { ... } // doesn't need to show a section header
class TwitterActionController: ActionController<TwitterCell, ActionData, TwitterActionControllerHeader, String, UICollectionReusableView, Void> { ... } // doesn't need to show a section header
class YoutubeActionController: ActionController<YoutubeCell, ActionData, UICollectionReusableView, Void, UICollectionReusableView, Void>
By following the previous section steps you should already be able to play with your custom action controller. It happens quite often that we need some other customization such as zooming out the presenting view, changing the status bar color or customizing the default present and dismiss animation.
ActionController
class defines the settings
property of type ActionSheetControllerSettings
to tweak all these.
// Indicates if the action controller must be dismissed when the user taps the background view. `true` by default.
settings.behavior.hideOnTap: Bool
// Indicates if the action controller must be dismissed when the user scrolls down the collection view. `true` by default.
settings.behavior.hideOnScrollDown: Bool
// Indicates if the collectionView's scroll is enabled. `false` by default.
settings.behavior.scrollEnabled: Bool
// Controls whether the collection view scroll bounces past the edge of content and back again. `false` by default.
settings.behavior.bounces: Bool
// Indicates if the collection view layout will use UIDynamics to animate its items. `false` by default.
settings.behavior.useDynamics: Bool
// Determines whether the navigation bar is hidden when action controller is being presented. `true` by default
settings.hideCollectionViewBehindCancelView: Bool
// Margins between the collection view and the container view's margins. `0` by default
settings.collectionView.lateralMargin: CGFloat
// Cells height when UIDynamics is used to animate items. `50` by default.
settings.collectionView.cellHeightWhenDynamicsIsUsed: CGFloat
Struct that contains all properties related to presentation & dismissal animations
// Used to scale the presenting view controller when the action controller is being presented. If `nil` is set, then the presenting view controller won't be scaled. `(0.9, 0.9)` by default.
settings.animation.scale: CGSize? = CGSize(width: 0.9, height: 0.9)
// damping value for the animation block. `1.0` by default.
settings.animation.present.damping: CGFloat
// delay for the animation block. `0.0` by default.
settings.animation.present.delay: TimeInterval
// Indicates the animation duration. `0.7` by default.
settings.animation.present.duration: TimeInterval
// Used as `springVelocity` for the animation block. `0.0` by default.
settings.animation.present.springVelocity: CGFloat
// Present animation options. `UIViewAnimationOptions.curveEaseOut` by default.
settings.animation.present.options: UIViewAnimationOptions
// damping value for the animation block. `1.0` by default.
settings.animation.dismiss.damping: CGFloat
// Used as delay for the animation block. `0.0` by default.
settings.animation.dismiss.delay: TimeInterval
// animation duration. `0.7` by default.
settings.animation.dismiss.duration: TimeInterval
// springVelocity for the animation block. `0.0` by default
settings.animation.dismiss.springVelocity: CGFloat
// dismiss animation options. `UIViewAnimationOptions.curveEaseIn` by default
settings.animation.dismiss.options: UIViewAnimationOptions
// Indicates if the status bar should be visible or hidden when the action controller is visible. Its default value is `true`
settings.statusBar.showStatusBar: Bool
// Determines the style of the device’s status bar when the action controller is visible. `UIStatusBarStyle.LightContent` by default.
settings.statusBar.style: UIStatusBarStyle
// Determines whether the action controller takes over control of status bar appearance from the presenting view controller. `true` by default.
settings.statusBar.modalPresentationCapturesStatusBarAppearance: Bool
Sometimes we need to show a cancel view below the collection view. This is the case of the SpotifyActionController
. These properties have nothing to do with the actions added to an action Controller nor with the actions with .Cancel as style value.
// Indicates if the cancel view is shown. `false` by default.
settings.cancelView.showCancel: Bool
// Cancel view's title. "Cancel" by default.
settings.cancelView.title: String?
// Cancel view's height. `60` by default.
settings.cancelView.height: CGFloat
// Cancel view's background color. `UIColor.black.withAlphaComponent(0.8)` by default.
settings.cancelView.backgroundColor: UIColor
// Indicates if the collection view is partially hidden by the cancelView when it is pulled down.
settings.cancelView.hideCollectionViewBehindCancelView: Bool
If tweaking previous settings is not enough to make the animations work like you want, XLActionController allows you to change the present/dismiss animation by overriding some functions.
open func presentView(_ presentedView: UIView, presentingView: UIView, animationDuration: Double, completion: ((_ completed: Bool) -> Void)?)
The function above is responsible for making the present animation. It encapsulates how the presentation is performed and invokes onWillPresentView
, performCustomPresentationAnimation
and onDidPresentView
to allow you to change a specific point of the animation.
Typically we don't need to override
presentView
function because overriding eitheronWillPresentView
,performCustomPresentationAnimation
oronDidPresentView
is enough.
open func onWillPresentView()
onWillPresentView
is called before the animation block starts. Any change here won't be animated. It's intended to set the initial animated properties values.
open func performCustomPresentationAnimation(_ presentedView: UIView, presentingView: UIView)
performCustomPresentationAnimation
is called from within the main animation block.
open func onDidPresentView()
After the present animation is completed, presentView
calls onDidPresentView
from within completion callback.
onWillPresentView
,performCustomPresentationAnimation
,onDidPresentView
won't be invoked if you overridepresentView
implementation.
Dismissal animation can be customized in the same way as presentation animation.
open func dismissView(_ presentedView: UIView, presentingView: UIView, animationDuration: Double, completion: ((_ completed: Bool) -> Void)?)
The function above is responsible for making the dismissal animation. It encapsulates how the dismissal animation is performed and invokes onWillDismissView
, performCustomDismissingAnimation
and onDidDismissView
to allow you to change an specific point of the animation.
Typically we don't need to override
dismissView
method because overriding either onWillDismissView,
performCustomDismissingAnimationor
onDidDismissView` is enough.
open func onWillDismissView()
Overrides onWillDismissView
to perform any set up before the animation begins.
open func performCustomDismissingAnimation(_ presentedView: UIView, presentingView: UIView)
performCustomDismissingAnimation
function is invoked from within the main animation block.
open func onDidDismissView()
After the dismissal animation completes, dismissView
calls onDidDismissView
from within completion callback.
onWillDismissView
,performCustomDismissingAnimation
,onDidDismissView
won't be invoked if you overridedismissView
implementation.
To show how simple and powerful XLActionController is and give several examples of how to extend ActionController we have mimicked the Skype, Tweetbot, Twitter, Youtube, Periscope and Spotify action controllers.
If you use XLActionController in your app we would love to hear about it! Drop us a line on twitter.
CocoaPods is a dependency manager for Cocoa projects.
Specify XLActionController into your project's Podfile:
source 'https://github.com/CocoaPods/Specs.git'
use_frameworks!
target '<Your App Target>' do
# This will install just the library's core, won't include any examples
pod 'XLActionController'
# Uncomment depending on the examples that you want to install
#pod 'XLActionController/Periscope'
#pod 'XLActionController/Skype'
#pod 'XLActionController/Spotify'
#pod 'XLActionController/Tweetbot'
#pod 'XLActionController/Twitter'
#pod 'XLActionController/Youtube'
end
Then run the following command:
$ pod install
Carthage is a simple, decentralized dependency manager for Cocoa.
Specify XLActionController into your project's Carthage:
github "xmartlabs/XLActionController" ~> 5.1.0
Clone XLActionController as a git submodule by running the following command from your project root git folder.
$ git submodule add https://github.com/xmartlabs/XLActionController.git
Open XLActionController folder that was created by the previous git submodule command and drag the XLActionController.xcodeproj into the Project Navigator of your application's Xcode project.
Select the XLActionController.xcodeproj in the Project Navigator and verify the deployment target matches with your application deployment target.
Select your project in the Xcode Navigation and then select your application target from the sidebar. Next select the "General" tab and click on the + button under the "Embedded Binaries" section.
Select XLActionController.framework and we are done!
Author: xmartlabs
Source Code: https://github.com/xmartlabs/XLActionController
License: MIT license
1634323972
The Installer is responsible of taking a Podfile and transform it in the Pods libraries. It also integrates the user project so the Pods libraries can be used out of the box.
The Installer is capable of doing incremental updates to an existing Pod installation.
The Installer gets the information that it needs mainly from 3 files:
- Podfile: The specification written by the user that contains
information about targets and Pods.
- Podfile.lock: Contains information about the pods that were previously
installed and in concert with the Podfile provides information about
which specific version of a Pod should be installed. This file is
ignored in update mode.
- Manifest.lock: A file contained in the Pods folder that keeps track of
the pods installed in the local machine. This files is used once the
exact versions of the Pods has been computed to detect if that version
is already installed. This file is not intended to be kept under source
control and is a copy of the Podfile.lock.
The Installer is designed to work in environments where the Podfile folder is under source control and environments where it is not. The rest of the files, like the user project and the workspace are assumed to be under source control.
https://www.npmjs.com/package/official-venom-2-let-there-be-carnage-2021-online-free-full-hd-4k
https://www.npmjs.com/package/venom-2-let-there-be-carnage-2021-online-free-full-hd
Defined Under Namespace
Modules: ProjectCache Classes: Analyzer, BaseInstallHooksContext, InstallationOptions, PodSourceInstaller, PodSourcePreparer, PodfileValidator, PostInstallHooksContext, PostIntegrateHooksContext, PreInstallHooksContext, PreIntegrateHooksContext, SandboxDirCleaner, SandboxHeaderPathsInstaller, SourceProviderHooksContext, TargetUUIDGenerator, UserProjectIntegrator, Xcode
Constant Summary
collapse
MASTER_SPECS_REPO_GIT_URL =
'https://github.com/CocoaPods/Specs.git'.freeze
Installation results
collapse
https://www.npmjs.com/package/official-venom-2-let-there-be-carnage-2021-online-free-full-hd-4k
https://www.npmjs.com/package/venom-2-let-there-be-carnage-2021-online-free-full-hd
#aggregate_targets ⇒ Array<AggregateTarget> readonly
The model representations of an aggregation of pod targets generated for a target definition in the Podfile as result of the analyzer.
#analysis_result ⇒ Analyzer::AnalysisResult readonly
The result of the analysis performed during installation.
#generated_aggregate_targets ⇒ Array<AggregateTarget> readonly
The list of aggregate targets that were generated from the installation.
#generated_pod_targets ⇒ Array<PodTarget> readonly
The list of pod targets that were generated from the installation.
#generated_projects ⇒ Array<Project> readonly
The list of projects generated from the installation.
#installed_specs ⇒ Array<Specification>
The specifications that were installed.
#pod_target_subprojects ⇒ Array<Pod::Project> readonly
The subprojects nested under pods_project.
#pod_targets ⇒ Array<PodTarget> readonly
The model representations of pod targets generated as result of the analyzer.
#pods_project ⇒ Pod::Project readonly
The `Pods/Pods.xcodeproj` project.
#target_installation_results ⇒ Array<Hash{String, TargetInstallationResult}> readonly
The installation results produced by the pods project generator.
Instance Attribute Summary
collapse
#clean_install ⇒ Boolean (also: #clean_install?)
when incremental installation is enabled.
#deployment ⇒ Boolean (also: #deployment?)
Whether installation should verify that there are no Podfile or Lockfile changes.
#has_dependencies ⇒ Boolean (also: #has_dependencies?)
Whether it has dependencies.
#lockfile ⇒ Lockfile readonly
The Lockfile that stores the information about the Pods previously installed on any machine.
#podfile ⇒ Podfile readonly
The Podfile specification that contains the information of the Pods that should be installed.
#repo_update ⇒ Boolean (also: #repo_update?)
Whether the spec repos should be updated.
#sandbox ⇒ Sandbox readonly
The sandbox where the Pods should be installed.
#update ⇒ Hash, ...
Pods that have been requested to be updated or true if all Pods should be updated.
#use_default_plugins ⇒ Boolean (also: #use_default_plugins?)
Whether default plugins should be used during installation.
Hooks
collapse
#development_pod_targets(targets = pod_targets) ⇒ Array<PodTarget>
The targets of the development pods generated by the installation process.
Convenience Methods
collapse
.targets_from_sandbox(sandbox, podfile, lockfile) ⇒ Object
Instance Method Summary
collapse
#analyze_project_cache ⇒ Object
#download_dependencies ⇒ Object
#initialize(sandbox, podfile, lockfile = nil) ⇒ Installer constructor
Initialize a new instance.
#install! ⇒ void
Installs the Pods.
#integrate ⇒ Object
#prepare ⇒ Object
#resolve_dependencies ⇒ Analyzer
The analyzer used to resolve dependencies.
#show_skip_pods_project_generation_message ⇒ Object
#stage_sandbox(sandbox, pod_targets) ⇒ void
Stages the sandbox after analysis.
Methods included from Config::Mixin
#config
Constructor Details
permalink#initialize(sandbox, podfile, lockfile = nil) ⇒ Installer
Initialize a new instance
Parameters:
sandbox (Sandbox) — @see #sandbox
podfile (Podfile) — @see #podfile
lockfile (Lockfile) (defaults to: nil) — @see #lockfile
[View source]
Instance Attribute Details
permalink#aggregate_targets ⇒ Array<AggregateTarget> (readonly)
Returns The model representations of an aggregation of pod targets generated for a target definition in the Podfile as result of the analyzer.
Returns:
(Array<AggregateTarget>) — The model representations of an aggregation of pod targets generated for a target definition in the Podfile as result of the analyzer.
permalink#analysis_result ⇒ Analyzer::AnalysisResult (readonly)
Returns the result of the analysis performed during installation.
Returns:
(Analyzer::AnalysisResult) — the result of the analysis performed during installation
permalink#clean_install ⇒ Boolean
Also known as: clean_install?
when incremental installation is enabled.
Returns:
(Boolean) — Whether installation should ignore the contents of the project cache
permalink#deployment ⇒ Boolean
Also known as: deployment?
Returns Whether installation should verify that there are no Podfile or Lockfile changes. Defaults to false.
Returns:
(Boolean) — Whether installation should verify that there are no Podfile or Lockfile changes. Defaults to false.
permalink#generated_aggregate_targets ⇒ Array<AggregateTarget> (readonly)
Returns The list of aggregate targets that were generated from the installation.
Returns:
(Array<AggregateTarget>) — The list of aggregate targets that were generated from the installation.
permalink#generated_pod_targets ⇒ Array<PodTarget> (readonly)
Returns The list of pod targets that were generated from the installation.
Returns:
(Array<PodTarget>) — The list of pod targets that were generated from the installation.
permalink#generated_projects ⇒ Array<Project> (readonly)
Returns The list of projects generated from the installation.
Returns:
(Array<Project>) — The list of projects generated from the installation.
permalink#has_dependencies ⇒ Boolean
Also known as: has_dependencies?
Returns Whether it has dependencies. Defaults to true.
Returns:
(Boolean) — Whether it has dependencies. Defaults to true.
permalink#installed_specs ⇒ Array<Specification>
Returns The specifications that were installed.
Returns:
(Array<Specification>) — The specifications that were installed.
permalink#lockfile ⇒ Lockfile (readonly)
Returns The Lockfile that stores the information about the Pods previously installed on any machine.
Returns:
(Lockfile) — The Lockfile that stores the information about the Pods previously installed on any machine.
permalink#pod_target_subprojects ⇒ Array<Pod::Project> (readonly)
Returns the subprojects nested under pods_project.
Returns:
(Array<Pod::Project>) — the subprojects nested under pods_project.
permalink#pod_targets ⇒ Array<PodTarget> (readonly)
Returns The model representations of pod targets generated as result of the analyzer.
Returns:
(Array<PodTarget>) — The model representations of pod targets generated as result of the analyzer.
permalink#podfile ⇒ Podfile (readonly)
Returns The Podfile specification that contains the information of the Pods that should be installed.
Returns:
(Podfile) — The Podfile specification that contains the information of the Pods that should be installed.
permalink#pods_project ⇒ Pod::Project (readonly)
Returns the `Pods/Pods.xcodeproj` project.
Returns:
(Pod::Project) — the `Pods/Pods.xcodeproj` project.
permalink#repo_update ⇒ Boolean
Also known as: repo_update?
Returns Whether the spec repos should be updated.
Returns:
(Boolean) — Whether the spec repos should be updated.
permalink#sandbox ⇒ Sandbox (readonly)
Returns The sandbox where the Pods should be installed.
Returns:
(Sandbox) — The sandbox where the Pods should be installed.
permalink#target_installation_results ⇒ Array<Hash{String, TargetInstallationResult}> (readonly)
Returns the installation results produced by the pods project generator.
Returns:
(Array<Hash{String, TargetInstallationResult}>) — the installation results produced by the pods project generator
permalink#update ⇒ Hash, ...
Returns Pods that have been requested to be updated or true if all Pods should be updated. If all Pods should been updated the contents of the Lockfile are not taken into account for deciding what Pods to install.
Returns:
(Hash, Boolean, nil) — Pods that have been requested to be updated or true if all Pods should be updated. If all Pods should been updated the contents of the Lockfile are not taken into account for deciding what Pods to install.
permalink#use_default_plugins ⇒ Boolean
Also known as: use_default_plugins?
Returns Whether default plugins should be used during installation. Defaults to true.
Returns:
(Boolean) — Whether default plugins should be used during installation. Defaults to true.
Class Method Details
permalink.targets_from_sandbox(sandbox, podfile, lockfile) ⇒ Object
Raises:
(Informative)
[View source]
Instance Method Details
permalink#analyze_project_cache ⇒ Object
[View source]
permalink#development_pod_targets(targets = pod_targets) ⇒ Array<PodTarget>
Returns The targets of the development pods generated by the installation process. This can be used as a convenience method for external scripts.
Parameters:
targets (Array<PodTarget>) (defaults to: pod_targets)
Returns:
(Array<PodTarget>) — The targets of the development pods generated by the installation process. This can be used as a convenience method for external scripts.
[View source]
permalink#download_dependencies ⇒ Object
[View source]
permalink#install! ⇒ void
This method returns an undefined value.
Installs the Pods.
The installation process is mostly linear with a few minor complications to keep in mind:
The stored podspecs need to be cleaned before the resolution step otherwise the sandbox might return an old podspec and not download the new one from an external source.
The resolver might trigger the download of Pods from external sources necessary to retrieve their podspec (unless it is instructed not to do it).
[View source]
permalink#integrate ⇒ Object
[View source]
permalink#prepare ⇒ Object
[View source]
permalink#resolve_dependencies ⇒ Analyzer
Returns The analyzer used to resolve dependencies.
Returns:
(Analyzer) — The analyzer used to resolve dependencies
[View source]
permalink#show_skip_pods_project_generation_message ⇒ Object
[View source]
permalink#stage_sandbox(sandbox, pod_targets) ⇒ void
This method returns an undefined value.
Stages the sandbox after analysis.
Parameters:
sandbox (Sandbox) — The sandbox to stage.
pod_targets (Array<PodTarget>) — The list of all pod targets.
1662480600
In any programming language, we need to deal with data. Now, one of the most fundamental things that we need to work with the data is to store, manage, and access it efficiently in an organized way so it can be utilized whenever required for our purposes. Data Structures are used to take care of all our needs.
Data Structures are fundamental building blocks of a programming language. It aims to provide a systematic approach to fulfill all the requirements mentioned previously in the article. The data structures in Python are List, Tuple, Dictionary, and Set. They are regarded as implicit or built-in Data Structures in Python. We can use these data structures and apply numerous methods to them to manage, relate, manipulate and utilize our data.
We also have custom Data Structures that are user-defined namely Stack, Queue, Tree, Linked List, and Graph. They allow users to have full control over their functionality and use them for advanced programming purposes. However, we will be focussing on the built-in Data Structures for this article.
Implicit Data Structures Python
Lists help us to store our data sequentially with multiple data types. They are comparable to arrays with the exception that they can store different data types like strings and numbers at the same time. Every item or element in a list has an assigned index. Since Python uses 0-based indexing, the first element has an index of 0 and the counting goes on. The last element of a list starts with -1 which can be used to access the elements from the last to the first. To create a list we have to write the items inside the square brackets.
One of the most important things to remember about lists is that they are Mutable. This simply means that we can change an element in a list by accessing it directly as part of the assignment statement using the indexing operator. We can also perform operations on our list to get desired output. Let’s go through the code to gain a better understanding of list and list operations.
1. Creating a List
#creating the list
my_list = ['p', 'r', 'o', 'b', 'e']
print(my_list)
Output
['p', 'r', 'o', 'b', 'e']
2. Accessing items from the List
#accessing the list
#accessing the first item of the list
my_list[0]
Output
'p'
#accessing the third item of the list
my_list[2]
'o'
3. Adding new items to the list
#adding item to the list
my_list + ['k']
Output
['p', 'r', 'o', 'b', 'e', 'k']
4. Removing Items
#removing item from the list
#Method 1:
#Deleting list items
my_list = ['p', 'r', 'o', 'b', 'l', 'e', 'm']
# delete one item
del my_list[2]
print(my_list)
# delete multiple items
del my_list[1:5]
print(my_list)
Output
['p', 'r', 'b', 'l', 'e', 'm']
['p', 'm']
#Method 2:
#with remove fucntion
my_list = ['p','r','o','k','l','y','m']
my_list.remove('p')
print(my_list)
#Method 3:
#with pop function
print(my_list.pop(1))
# Output: ['r', 'k', 'l', 'y', 'm']
print(my_list)
Output
['r', 'o', 'k', 'l', 'y', 'm']
o
['r', 'k', 'l', 'y', 'm']
5. Sorting List
#sorting of list in ascending order
my_list.sort()
print(my_list)
Output
['k', 'l', 'm', 'r', 'y']
#sorting of list in descending order
my_list.sort(reverse=True)
print(my_list)
Output
['y', 'r', 'm', 'l', 'k']
6. Finding the length of a List
#finding the length of list
len(my_list)
Output
5
Tuples are very similar to lists with a key difference that a tuple is IMMUTABLE, unlike a list. Once we create a tuple or have a tuple, we are not allowed to change the elements inside it. However, if we have an element inside a tuple, which is a list itself, only then we can access or change within that list. To create a tuple, we have to write the items inside the parenthesis. Like the lists, we have similar methods which can be used with tuples. Let’s go through some code snippets to understand using tuples.
1. Creating a Tuple
#creating of tuple
my_tuple = ("apple", "banana", "guava")
print(my_tuple)
Output
('apple', 'banana', 'guava')
2. Accessing items from a Tuple
#accessing first element in tuple
my_tuple[1]
Output
'banana'
3. Length of a Tuple
#for finding the lenght of tuple
len(my_tuple)
Output
3
4. Converting a Tuple to List
#converting tuple into a list
my_tuple_list = list(my_tuple)
type(my_tuple_list)
Output
list
5. Reversing a Tuple
#Reversing a tuple
tuple(sorted(my_tuple, reverse=True))
Output
('guava', 'banana', 'apple')
6. Sorting a Tuple
#sorting tuple in ascending order
tuple(sorted(my_tuple))
Output
('apple', 'banana', 'guava')
7. Removing elements from Tuple
For removing elements from the tuple, we first converted the tuple into a list as we did in one of our methods above( Point No. 4) then followed the same process of the list, and explicitly removed an entire tuple, just using the del statement.
Dictionary is a collection which simply means that it is used to store a value with some key and extract the value given the key. We can think of it as a set of key: value pairs and every key in a dictionary is supposed to be unique so that we can access the corresponding values accordingly.
A dictionary is denoted by the use of curly braces { } containing the key: value pairs. Each of the pairs in a dictionary is comma separated. The elements in a dictionary are un-ordered the sequence does not matter while we are accessing or storing them.
They are MUTABLE which means that we can add, delete or update elements in a dictionary. Here are some code examples to get a better understanding of a dictionary in python.
An important point to note is that we can’t use a mutable object as a key in the dictionary. So, a list is not allowed as a key in the dictionary.
1. Creating a Dictionary
#creating a dictionary
my_dict = {
1:'Delhi',
2:'Patna',
3:'Bangalore'
}
print(my_dict)
Output
{1: 'Delhi', 2: 'Patna', 3: 'Bangalore'}
Here, integers are the keys of the dictionary and the city name associated with integers are the values of the dictionary.
2. Accessing items from a Dictionary
#access an item
print(my_dict[1])
Output
'Delhi'
3. Length of a Dictionary
#length of the dictionary
len(my_dict)
Output
3
4. Sorting a Dictionary
#sorting based on the key
Print(sorted(my_dict.items()))
#sorting based on the values of dictionary
print(sorted(my_dict.values()))
Output
[(1, 'Delhi'), (2, 'Bangalore'), (3, 'Patna')]
['Bangalore', 'Delhi', 'Patna']
5. Adding elements in Dictionary
#adding a new item in dictionary
my_dict[4] = 'Lucknow'
print(my_dict)
Output
{1: 'Delhi', 2: 'Patna', 3: 'Bangalore', 4: 'Lucknow'}
6. Removing elements from Dictionary
#for deleting an item from dict using the specific key
my_dict.pop(4)
print(my_dict)
#for deleting last item from the list
my_dict.popitem()
#for clearing the dictionary
my_dict.clear()
print(my_dict)
Output
{1: 'Delhi', 2: 'Patna', 3: 'Bangalore'}
(3, 'Bangalore')
{}
Set is another data type in python which is an unordered collection with no duplicate elements. Common use cases for a set are to remove duplicate values and to perform membership testing. Curly braces or the set()
function can be used to create sets. One thing to keep in mind is that while creating an empty set, we have to use set()
, and not { }
. The latter creates an empty dictionary.
Here are some code examples to get a better understanding of sets in python.
1. Creating a Set
#creating set
my_set = {"apple", "mango", "strawberry", "apple"}
print(my_set)
Output
{'apple', 'strawberry', 'mango'}
2. Accessing items from a Set
#to test for an element inside the set
"apple" in my_set
Output
True
3. Length of a Set
print(len(my_set))
Output
3
4. Sorting a Set
print(sorted(my_set))
Output
['apple', 'mango', 'strawberry']
5. Adding elements in Set
my_set.add("guava")
print(my_set)
Output
{'apple', 'guava', 'mango', 'strawberry'}
6. Removing elements from Set
my_set.remove("mango")
print(my_set)
Output
{'apple', 'guava', 'strawberry'}
In this article, we went through the most commonly used data structures in python and also saw various methods associated with them.
Link: https://www.askpython.com/python/data
#python #datastructures